英文:
Wrap XML sibling tags in a parent tag with XSLT
问题
I have a set of sibling tags that look like this in a much larger document:
<?xml version="1.0" encoding="UTF-8"?>
<foo>
<a>some text</a>, '<b>some text</b>', <c><d>some text</d> <e>sometext</e></c>
</foo>
The requirement is that the transform matches tag a
followed by ",", followed by tag b
, then tag c
. These are then wrapped in an outer tag. Below is a simplified representation of what I would like the document to look like:
<?xml version="1.0" encoding="UTF-8"?>
<foo>
<bar><a>some text</a>, '<b>some text</b>', <c><d>some text</d> <e>sometext</e></c></bar>
</foo>
However, I want this to be done in place in a much larger document without disturbing any other tags.
Basically, I am attempting to match the pattern above in the nodes in the document, then wrap the pattern in a parent tag and delete the old nodes so I do not have duplicates in the output. Is there a way to do that cleanly in XSLT?
英文:
I have a set of sibling tags that look like this in a much larger document:
<?xml version="1.0" encoding="UTF-8"?>
<foo>
<a>some text</a>, '<b>some text</b>', <c><d>some text</d> <e>sometext</e></c>
</foo>
The requirement is that the transform matches tag a followed by "," followed by tag b, then tag c. These are then wrapped in an outer tag. Below is a simplified representation of what I would like the document to look like:
<?xml version="1.0" encoding="UTF-8"?>
<foo>
<bar><a>some text</a>, `<b>some text</b>', <c><d>some text</d> <e>sometext</e></c></bar>
</foo>
However, I want this to be done in place in a much larger document without disturbing any other tags.
Basically, I am attempting to match the pattern above in the nodes in the document then wrap the pattern in a parent tag and delete the old nodes so I do not have duplicates in the output. Is there away to do that cleanly in XSLT?
答案1
得分: 0
这是一个有点奇怪的序列,所以我能够得出的答案是一种有点奇怪的组合,使用了for-each-group group-starting-with
和for-each-group group-adjacent
(将检查委托给一个函数,你可能需要调整该函数以确切地检查你的节点是否符合预期):
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:mf="http://example.com/mf"
exclude-result-prefixes="#all"
version="3.0">
<xsl:function name="mf:adjacent-predicate" as="xs:boolean">
<xsl:param name="node" as="node()"/>
<xsl:param name="pos" as="xs:integer"/>
<xsl:sequence
select="$pos eq 1 and $node instance of element(a) or
$pos = (2,4) and $node instance of text() and contains($node, ',') or
$pos eq 3 and $node instance of element(b) or
$pos eq 5 and $node instance of element(c)"/>
</xsl:function>
<xsl:mode on-no-match="shallow-copy"/>
<xsl:template match="*[a]">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:for-each-group select="node()" group-starting-with="a">
<xsl:choose>
<xsl:when test="self::a">
<xsl:for-each-group select="current-group()" group-adjacent="mf:adjacent-predicate(., position())">
<xsl:choose>
<xsl:when test="current-grouping-key()">
<bar>
<xsl:apply-templates select="current-group()"/>
</bar>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="current-group()"/>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="current-group()"/>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
英文:
It is kind of an odd sequence so all I have been able to come with is a bit of an odd combination of a for-each-group group-starting-with
plus for-each-group group-adjacent
(delegating the check to a function you probably need to adjust to check your nodes exactly as you expect them):
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:mf="http://example.com/mf"
exclude-result-prefixes="#all"
version="3.0">
<xsl:function name="mf:adjacent-predicate" as="xs:boolean">
<xsl:param name="node" as="node()"/>
<xsl:param name="pos" as="xs:integer"/>
<xsl:sequence
select="$pos eq 1 and $node instance of element(a) or
$pos = (2,4) and $node instance of text() and contains($node, ',') or
$pos eq 3 and $node instance of element(b) or
$pos eq 5 and $node instance of element(c)"/>
</xsl:function>
<xsl:mode on-no-match="shallow-copy"/>
<xsl:template match="*[a]">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:for-each-group select="node()" group-starting-with="a">
<xsl:choose>
<xsl:when test="self::a">
<xsl:for-each-group select="current-group()" group-adjacent="mf:adjacent-predicate(., position())">
<xsl:choose>
<xsl:when test="current-grouping-key()">
<bar>
<xsl:apply-templates select="current-group()"/>
</bar>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="current-group()"/>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="current-group()"/>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论