当我需要考虑两个 xml 节点的内容时,如何使用 XPath 1.0 在 XML 中找到不同的节点
How do I find distinct nodes in an XML with XPath 1.0 when I need to take the content of two xml nodes into account
这是我的第一个问题。
我正在尝试创建一个将 XML 转换为文本的 xslt。
我需要找到 LANG 和 OFFICEID 连接的不同列表,然后可以在 xsl:for-每个 循环
我已经创建了我正在使用的 XML 的最小版本
<docinfo>
<printfile customer="Migrol">
<envelope postagetype="A">
<index name="LANG" value="G"/>
<index name="OFFICEID" value="500"/>
</envelope>
<envelope postagetype="A">
<index name="LANG" value="F"/>
<index name="OFFICEID" value="500"/>
</envelope>
<envelope postagetype="A">
<index name="LANG" value="G"/>
<index name="OFFICEID" value="500"/>
</envelope>
<envelope postagetype="A">
<index name="LANG" value="I"/>
<index name="OFFICEID" value="300"/>
</envelope>
<envelope postagetype="A">
<index name="LANG" value="G"/>
<index name="OFFICEID" value="100"/>
</envelope>
<envelope postagetype="A">
<index name="LANG" value="G"/>
<index name="OFFICEID" value="100"/>
</envelope>
<envelope postagetype="A">
<index name="LANG" value="I"/>
<index name="OFFICEID" value="300"/>
</envelope>
<envelope postagetype="A">
<index name="LANG" value="G"/>
<index name="OFFICEID" value="500"/>
</envelope>
</printfile>
</docinfo>
对于 XPath 2.0,这可以通过使用语句
来解决
/docinfo/printfile/distinct-values(envelope/concat(index[@name='OFFICEID']/@value, index[@name='LANG']/@value))
或
/docinfo/printfile/envelope[not(concat(index[@name='OFFICEID']/@value, index[@name='LANG']/@value)=preceding-sibling::envelope/concat(index[@name='OFFICEID']/@value, index[@name='LANG']/@value))]/concat(index[@name='OFFICEID']/@value, index[@name='LANG']/@value)
很遗憾,我还没有找到在 XPath 1.0 中实现这一点的方法。 concat 函数似乎给我带来了麻烦。
我想使用的 XSLT 的简单版本
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:template match="printfile">
<xsl:for-each select="/docinfo/printfile/envelope[not(concat(index[@name='OFFICEID']/@value, index[@name='LANG']/@value)=preceding-sibling::envelope/concat(index[@name='OFFICEID']/@value, index[@name='LANG']/@value))]">
<xsl:variable name="OID" select="index[@name='OFFICEID'][1]/@value"/>
<xsl:variable name="LANG" select="index[@name='LANG'][1]/@value"/>
<xsl:value-of select="$OID"/>
<xsl:text> </xsl:text>
<xsl:value-of select="$LANG"/>
<xsl:text> </xsl:text>
</xsl:for-each>
</xsl:template>
<!-- suppress default text -->
<xsl:template match="text()"/>
</xsl:stylesheet>
结果应该类似于
"500 G"
"500 F"
"300 I"
"100 G"
有没有人对如何使用 XSLT 和 XPath 1.0 实现这一目标提出建议
在 XSLT 1.0 中提取不同值的首选方法是 Muenchian grouping。
在您的示例中,您需要使用复合键:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:key name="env" match="envelope" use="concat(index[@name='OFFICEID']/@value, index[@name='LANG']/@value)" />
<xsl:template match="/docinfo">
<xsl:for-each select="printfile/envelope[count(. | key('env', concat(index[@name='OFFICEID']/@value, index[@name='LANG']/@value))[1]) = 1]">
<xsl:value-of select="index[@name='OFFICEID']/@value"/>
<xsl:text> </xsl:text>
<xsl:value-of select="index[@name='LANG']/@value"/>
<xsl:text> </xsl:text>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
请注意,在大多数情况下,您会在定义密钥时包含一个分隔符,例如
<xsl:key name="env" match="envelope" use="concat(index[@name='OFFICEID']/@value, '|', index[@name='LANG']/@value)" />
防止误报。
这是我的第一个问题。
我正在尝试创建一个将 XML 转换为文本的 xslt。 我需要找到 LANG 和 OFFICEID 连接的不同列表,然后可以在 xsl:for-每个 循环
我已经创建了我正在使用的 XML 的最小版本
<docinfo>
<printfile customer="Migrol">
<envelope postagetype="A">
<index name="LANG" value="G"/>
<index name="OFFICEID" value="500"/>
</envelope>
<envelope postagetype="A">
<index name="LANG" value="F"/>
<index name="OFFICEID" value="500"/>
</envelope>
<envelope postagetype="A">
<index name="LANG" value="G"/>
<index name="OFFICEID" value="500"/>
</envelope>
<envelope postagetype="A">
<index name="LANG" value="I"/>
<index name="OFFICEID" value="300"/>
</envelope>
<envelope postagetype="A">
<index name="LANG" value="G"/>
<index name="OFFICEID" value="100"/>
</envelope>
<envelope postagetype="A">
<index name="LANG" value="G"/>
<index name="OFFICEID" value="100"/>
</envelope>
<envelope postagetype="A">
<index name="LANG" value="I"/>
<index name="OFFICEID" value="300"/>
</envelope>
<envelope postagetype="A">
<index name="LANG" value="G"/>
<index name="OFFICEID" value="500"/>
</envelope>
</printfile>
</docinfo>
对于 XPath 2.0,这可以通过使用语句
来解决/docinfo/printfile/distinct-values(envelope/concat(index[@name='OFFICEID']/@value, index[@name='LANG']/@value))
或
/docinfo/printfile/envelope[not(concat(index[@name='OFFICEID']/@value, index[@name='LANG']/@value)=preceding-sibling::envelope/concat(index[@name='OFFICEID']/@value, index[@name='LANG']/@value))]/concat(index[@name='OFFICEID']/@value, index[@name='LANG']/@value)
很遗憾,我还没有找到在 XPath 1.0 中实现这一点的方法。 concat 函数似乎给我带来了麻烦。
我想使用的 XSLT 的简单版本
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:template match="printfile">
<xsl:for-each select="/docinfo/printfile/envelope[not(concat(index[@name='OFFICEID']/@value, index[@name='LANG']/@value)=preceding-sibling::envelope/concat(index[@name='OFFICEID']/@value, index[@name='LANG']/@value))]">
<xsl:variable name="OID" select="index[@name='OFFICEID'][1]/@value"/>
<xsl:variable name="LANG" select="index[@name='LANG'][1]/@value"/>
<xsl:value-of select="$OID"/>
<xsl:text> </xsl:text>
<xsl:value-of select="$LANG"/>
<xsl:text> </xsl:text>
</xsl:for-each>
</xsl:template>
<!-- suppress default text -->
<xsl:template match="text()"/>
</xsl:stylesheet>
结果应该类似于
"500 G"
"500 F"
"300 I"
"100 G"
有没有人对如何使用 XSLT 和 XPath 1.0 实现这一目标提出建议
在 XSLT 1.0 中提取不同值的首选方法是 Muenchian grouping。
在您的示例中,您需要使用复合键:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:key name="env" match="envelope" use="concat(index[@name='OFFICEID']/@value, index[@name='LANG']/@value)" />
<xsl:template match="/docinfo">
<xsl:for-each select="printfile/envelope[count(. | key('env', concat(index[@name='OFFICEID']/@value, index[@name='LANG']/@value))[1]) = 1]">
<xsl:value-of select="index[@name='OFFICEID']/@value"/>
<xsl:text> </xsl:text>
<xsl:value-of select="index[@name='LANG']/@value"/>
<xsl:text> </xsl:text>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
请注意,在大多数情况下,您会在定义密钥时包含一个分隔符,例如
<xsl:key name="env" match="envelope" use="concat(index[@name='OFFICEID']/@value, '|', index[@name='LANG']/@value)" />
防止误报。