开发者

XSLT, how to fetch and output combined elements

Dear community, it would be great if you could give me an advice on how to transform this:

<div>  
something  
   <title>   this title  </title>  
    something else  
</div>  

into

<div>  
<title1>
something  </title1>  
<title2>  this title  </title2>  
<title3>  something else  </title>
</div>

Unfortunately the substring-before/after method cannot be used as there is an inner element inside div. Moreover, copy-of seems like it doesn't work with substring either. Do you have any advice on how to transform the开发者_C百科 above xml?


This stylesheet:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="div/text()|div/*">
        <xsl:element name="title{position()}">
            <xsl:value-of select="normalize-space(self::text())"/>
            <xsl:apply-templates/>
        </xsl:element>
    </xsl:template>
</xsl:stylesheet>

Output:

<div>
    <title1>something</title1>
    <title2> this title </title2>
    <title3>something else</title3>
</div>


This solution is a little bit more precise and more general at the same time:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:template match="node()|@*">
     <xsl:copy>
       <xsl:apply-templates select="node()|@*"/>
     </xsl:copy>
 </xsl:template>

 <xsl:template match="/*/node()">
  <xsl:element name="title{position()}">
   <xsl:copy-of select="translate(self::text()|node(), '&#xA;&#xD;', '  ')"/>
  </xsl:element>
 </xsl:template>
</xsl:stylesheet>

When applied on the provided XML document:

<div>
something      
    <title>   this title  </title>
     something else
</div>

a more closer to the desired result is produced (only NL or CR characters are converted to space):

<div>
   <title1> something           </title1>
   <title2>   this title  </title2>
   <title3>      something else </title3>
</div>


Edit

I just realized that my output doesn't match yours.
But @Alejandro's solution is perfect, so I hope you won't be too upset about this one.


I came up with this solution:

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" encoding="UTF-8" indent="yes"/>

    <xsl:template match="/">
        <xsl:element name="div">
            <xsl:apply-templates />
        </xsl:element>
    </xsl:template>

    <xsl:template match="div/text()|div/title/text()">
        <xsl:element name="title{position()}">
            <xsl:copy-of select="normalize-space(.)" />
        </xsl:element>
    </xsl:template>
</xsl:stylesheet>

which produces this output:

<?xml version="1.0" encoding="UTF-8"?>
<div>
    <title1>something</title1>
    <title1>this title</title1>
    <title3>something else</title3>
</div>
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜