在第一次xsl转换之后,我有一个类似于以下的xml输出:
<?xml version="1.0" encoding="UTF-8"?>
<analysis type="1">
<file path="a.txt">
<line nb="23" found="true"/>
<line nb="36" found="true" count="2"/>
<line nb="98" found="true"/>
</file>
<file path="a.txt">
<line nb="100" found="false"/>
</file>
<file path="b.txt">
<line nb="10" found="false"/>
</file>
<!-- more file nodes below with different @path -->
</analysis>
但现在我需要获得第二个输出,其中file
节点合并,如果它们具有相同的path
属性,如下所示:
<?xml version="1.0" encoding="UTF-8"?>
<analysis type="1">
<file path="a.txt">
<line nb="23" found="true"/>
<line nb="36" found="true" count="2"/>
<line nb="98" found="true"/>
<line nb="100" found="false"/>
</file>
<file path="b.txt">
<line nb="10" found="false"/>
</file>
</analysis>
我不知道可能的@path
值。
我看了很多关于节点合并的帖子,但找不到一种方法来做我想要的。我失去了节点分组,密钥,id生成…到目前为止只获得了错误消息。
你能帮我从第一个输出(xls 1.0)开始得到第二个输出吗?如果你能提供一些参考(网站),在那里我可以找到关于这种转换的解释,那就太好了。
注意:具有相同@path
的两个file
节点的两个line
节点的@nb
属性永远不会碰撞,它是唯一的,即永远不会发生这种情况:
<?xml version="1.0" encoding="UTF-8"?>
<analysis type="1">
<file path="a.txt">
<line nb="36" found="true" count="2"/>
</file>
<file path="a.txt">
<line nb="36" found="true"/>
</file>
</analysis>
非常感谢您的帮助
不带键的XPath 1.0
既然你在问题中说你在理解键方面有困难,这里有一种方法可以在没有键的情况下做到,使用一种称为兄弟递归的技术。它被认为不如使用键好,因为它使用兄弟轴,这通常是相当慢的。然而,在大多数实际情况下,您不会注意到差异:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:template match="node() | @*">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="analysis">
<xsl:copy>
<xsl:copy-of select="@*" />
<xsl:apply-templates select="file[not(preceding-sibling::file/@path = @path)]" mode="sibling-recurse" />
</xsl:copy>
</xsl:template>
<xsl:template match="file" mode="sibling-recurse">
<xsl:copy>
<!-- back to default mode -->
<xsl:apply-templates select="node() | @*" />
<xsl:apply-templates select="following-sibling::file[current()/@path = @path]" />
</xsl:copy>
</xsl:template>
<xsl:template match="file">
<xsl:apply-templates select="node()" />
</xsl:template>
</xsl:stylesheet>
带键的XPath 1.0,用于 nchian分组
这种方法使用了m
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:key match="file" use="@path" name="path" />
<xsl:template match="node() | @*">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="analysis">
<xsl:copy>
<xsl:copy-of select="@*" />
<xsl:apply-templates select="file[generate-id(.) = generate-id(key('path', @path))]" mode="sibling-recurse" />
</xsl:copy>
</xsl:template>
<xsl:template match="file" mode="sibling-recurse">
<xsl:copy>
<!-- back to default mode -->
<xsl:apply-templates select="node() | @*" />
<xsl:apply-templates select="following-sibling::file[@path = current()/@path]/node()" />
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
注意:对于这两种方法,模式切换都不是完全必要的,但它使编写简单的匹配模式更容易,并防止优先级冲突或难以发现的bug (imo)。