这是我的第一个问题。
我正在尝试创建一个将XML转换为Text的xslt。 我需要找到 Lang 和 OFFICEID 串联的不同列表,然后可以将其用于 xsl:for-each 循环>
我已经创建了一个最小的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,可以使用Statement来解决
/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实现这一目标吗?
答案 0 :(得分: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)" />
防止误报。