Reputation: 167
I am beginner in XSLT and XPath, learning mostly by example and working on a project.
I am trying to concatenate text()
content of two nodes. With each apperance of node a
, the text()
content of node a
should be concatenated with text()
content of next following sibling node b
. This concatenated content should be registered as text()
new node foo
in the same place, as node a
was.
Example input:
<html>
<body>
<a>First text</a>
<b>Text</b>
<c>Indiferent tag.</c>
<a>Another "a" test.</a>
<b>ěščřžýáíéúů</b>
<c>Another indiferent tag.</c>
</body>
</html>
Expected (hoped for) output:
<html>
<body>
<foo>First text Text</foo>
<c>Indiferent tag.</c>
<foo>Another "a" test. ěščřžýáíéúů</foo>
<c>Another indiferent tag.</c>
</body>
</html>
Stylesheet I am currently using:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" encoding="utf-8"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="html/body/a">
<foo>
<xsl:value-of select="concat(text(), folowing-sibling::b[1]/text())"/>
</foo>
</xsl:template>
Just errors out because of wrong XPath statement.
How can I improve the stylesheet to get desired result?
Note: I am aware of existence of following issues and its answers: Here, This brilliant answer and others, but I am having trouble applying them to my specific case.
Furthermore, for this project I am stuck with python lxml
; which I believe is I can use only XSLT 1.0 and XPath 1.0. Those are limits that I would like for anybody kind enough to help me to follow. However, I am learning with saxon
, so solutions using advanced versions would be also nice from learning perspective.
Lastly, this is just a example snippet from larger HTML file, which I am trying to convert to valid (and for my use case handy) XML, and there is a lot of grouping involved (I would need to group by key foo
as well eventually), so the solution should preferably use identity transform overloading, which will hopefully enable me to use it beyond this example ...
Upvotes: 0
Views: 277
Reputation: 2714
Here's a way you could do this.
Not sure about your grouping comment at the end of your question though...
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" encoding="utf-8"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="a">
<foo>
<xsl:value-of select="concat(., following-sibling::b[1])"/>
</foo>
</xsl:template>
<!-- Remove b nodes -->
<xsl:template match="b"/>
</xsl:stylesheet>
See it working here: https://xsltfiddle.liberty-development.net/jxDjin9
Upvotes: 1