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(), '

', ' ')"/>
</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>
精彩评论