使用 XSLT 检索 XML 中的属性值
Retrieving value of attributes in XML using XSLT
要扩展提供的解决方案 here,目的是检索属性的值及其名称。
对于此文档,
<a>
<apple color="red"/>
<apple color="green"/>
<banana color="yellow"/>
<sugar taste="sweet"/>
<cat size="small"/>
</a>
上面post中的代码提供了这个结果:
For tags: apple 2, banana 1, sugar 1, cat 1
For attributes: color 3, taste 1, size 1
现在,期望的结果是:
For tags: apple 2, banana 1, sugar 1, cat 1
For attributes: color(red) 1, color(green) 1, color(yellow) 1, taste(sweet) 1, size (small) 1
非常感谢。
要扩展 Rudramuni TP 提供的 solution for your previous question,您可以添加一个额外的键来获取唯一的属性值:
<xsl:key name="kAttribValue" match="@*" use="."/>
和一个附加变量:
<xsl:variable name="var2">
<xsl:for-each select="/a/*/@*[generate-id() = generate-id(key('kAttribValue', .))]">
<xsl:value-of select="concat(name(.), '(', .,')', ' ', count(key('kAttribValue', .)))"/>
<xsl:if test="not(position()=last())">
<xsl:text>, </xsl:text>
</xsl:if>
</xsl:for-each>
</xsl:variable>
通过对 Rudramuni TP 代码的这些调整:
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" omit-xml-declaration="yes"/>
<xsl:key name="kEleName" match="*" use="local-name()"/>
<xsl:key name="kAttribName" match="@*" use="local-name()"/>
<xsl:key name="kAttribValue" match="@*" use="."/>
<xsl:variable name="var1">
<xsl:for-each select="/a/*/@*[generate-id() = generate-id(key('kAttribName', name()))]">
<xsl:value-of select="concat(name(.), ' ', count(key('kAttribName', name(.))))"/>
<xsl:if test="not(position()=last())">
<xsl:text>, </xsl:text>
</xsl:if>
</xsl:for-each>
</xsl:variable>
<xsl:variable name="var2">
<xsl:for-each select="/a/*/@*[generate-id() = generate-id(key('kAttribValue', .))]">
<xsl:value-of select="concat(name(.), '(', .,')', ' ', count(key('kAttribValue', .)))"/>
<xsl:if test="not(position()=last())">
<xsl:text>, </xsl:text>
</xsl:if>
</xsl:for-each>
</xsl:variable>
<xsl:template match="/*">
<xsl:apply-templates select="*[generate-id() = generate-id(key('kEleName', name()))]"/>
</xsl:template>
<xsl:template match="*">
<xsl:if test="position()=1"><xsl:text>For tags: </xsl:text></xsl:if>
<xsl:value-of select="concat(name(.), ' ', count(key('kEleName', name(.))))"/>
<xsl:if test="following-sibling::*">
<xsl:text>, </xsl:text>
</xsl:if>
<xsl:if test="position()=last()">
<xsl:text> For attributes: </xsl:text>
<xsl:value-of select="$var2"/>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
应用于您的输入时 XML
<a>
<apple color="red"/>
<apple color="green"/>
<banana color="yellow"/>
<sugar taste="sweet"/>
<cat size="small"/>
</a>
生成扩展结果:
For tags: apple 2, banana 1, sugar 1, cat 1
For attributes: color(red) 1, color(green) 1, color(yellow) 1, taste(sweet) 1, size(small) 1
更新: 如评论中所述,上述调整(以及上一个问题的答案)仅适用于问题中提供的输入。给定输入 XML,例如
<root>
<a>
<apple color="red"/>
<apple color="green"/>
<banana color="yellow"/>
<sugar taste="sweet"/>
<cat size="small"/>
</a>
<a>
<apple color="red"/>
<apple color="green"/>
<banana color="yellow"/>
<sugar taste="sweet"/>
<dog size="big"/>
</a>
</root>
模板可以调整如下:
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" omit-xml-declaration="yes"/>
<xsl:key name="kEleName" match="*" use="local-name()"/>
<xsl:key name="kAttribName" match="@*" use="local-name()"/>
<xsl:key name="kAttribValue" match="@*" use="."/>
<xsl:variable name="var1">
<xsl:for-each select="//a/*/@*[generate-id() = generate-id(key('kAttribValue', .))]">
<xsl:value-of select="concat(name(.), ' (', .,')', ' ', count(key('kAttribValue', .)))"/>
<xsl:if test="not(position()=last())">
<xsl:text>, </xsl:text>
</xsl:if>
</xsl:for-each>
</xsl:variable>
<xsl:template match="/*">
<xsl:apply-templates select="a/*[generate-id() = generate-id(key('kEleName', name()))]"/>
</xsl:template>
<xsl:template match="*">
<xsl:if test="position()=1"><xsl:text>For tags: </xsl:text></xsl:if>
<xsl:value-of select="concat(name(.), ' ', count(key('kEleName', name(.))))"/>
<xsl:if test="following::*">
<xsl:text>, </xsl:text>
</xsl:if>
<xsl:if test="position()=last()">
<xsl:text> For attributes: </xsl:text>
<xsl:value-of select="$var1"/>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
将其应用于调整后的示例输入时 XML 会生成输出:
For tags: apple 4, banana 2, sugar 2, cat 1, dog 1
For attributes: color (red) 2, color (green) 2, color (yellow) 2, taste (sweet) 2, size (small) 1, size (big) 1
调整如下:本次
<xsl:for-each select="/a/*/@*[generate-id() = generate-id(key('kAttribValue', .))]">
必须调整为
<xsl:for-each select="//a/*/@*[generate-id() = generate-id(key('kAttribValue', .))]">
否则只有第一个 a
节点的子节点的属性被匹配。
这个
<xsl:apply-templates select="*[generate-id() = generate-id(key('kEleName', name()))]"/>
必须调整为
<xsl:apply-templates select="a/*[generate-id() = generate-id(key('kEleName', name()))]"/>
否则将选择 a
标签(这将产生输出
For tags: a 2,
)。
还有这个
<xsl:if test="following-sibling::*">
<xsl:text>, </xsl:text>
</xsl:if>
必须调整为
<xsl:if test="following::*">
<xsl:text>, </xsl:text>
</xsl:if>
因为在第二个 a
节点中添加的 dog
不是 following sibling 但仍然是 following元素。
很明显,如果未知要求允许具有不同的命名父节点,则此调整将不会工作 - 作为简化的示例,它不适用于像[=这样的输入32=]
<a>
<apple color="red"/>
<apple color="green"/>
</a>
<b>
<banana color="yellow"/>
</b>
如果不同的父节点或嵌套结构,例如
<a>
<apple color="red"/>
<apple color="green"/>
<b>
<banana color="yellow"/>
</b>
</a>
也应该处理,我建议为此提出一个新问题,因为这与问题中提供的示例输入 XML 差异太大。
要扩展提供的解决方案 here,目的是检索属性的值及其名称。
对于此文档,
<a>
<apple color="red"/>
<apple color="green"/>
<banana color="yellow"/>
<sugar taste="sweet"/>
<cat size="small"/>
</a>
上面post中的代码提供了这个结果:
For tags: apple 2, banana 1, sugar 1, cat 1
For attributes: color 3, taste 1, size 1
现在,期望的结果是:
For tags: apple 2, banana 1, sugar 1, cat 1
For attributes: color(red) 1, color(green) 1, color(yellow) 1, taste(sweet) 1, size (small) 1
非常感谢。
要扩展 Rudramuni TP 提供的 solution for your previous question,您可以添加一个额外的键来获取唯一的属性值:
<xsl:key name="kAttribValue" match="@*" use="."/>
和一个附加变量:
<xsl:variable name="var2">
<xsl:for-each select="/a/*/@*[generate-id() = generate-id(key('kAttribValue', .))]">
<xsl:value-of select="concat(name(.), '(', .,')', ' ', count(key('kAttribValue', .)))"/>
<xsl:if test="not(position()=last())">
<xsl:text>, </xsl:text>
</xsl:if>
</xsl:for-each>
</xsl:variable>
通过对 Rudramuni TP 代码的这些调整:
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" omit-xml-declaration="yes"/>
<xsl:key name="kEleName" match="*" use="local-name()"/>
<xsl:key name="kAttribName" match="@*" use="local-name()"/>
<xsl:key name="kAttribValue" match="@*" use="."/>
<xsl:variable name="var1">
<xsl:for-each select="/a/*/@*[generate-id() = generate-id(key('kAttribName', name()))]">
<xsl:value-of select="concat(name(.), ' ', count(key('kAttribName', name(.))))"/>
<xsl:if test="not(position()=last())">
<xsl:text>, </xsl:text>
</xsl:if>
</xsl:for-each>
</xsl:variable>
<xsl:variable name="var2">
<xsl:for-each select="/a/*/@*[generate-id() = generate-id(key('kAttribValue', .))]">
<xsl:value-of select="concat(name(.), '(', .,')', ' ', count(key('kAttribValue', .)))"/>
<xsl:if test="not(position()=last())">
<xsl:text>, </xsl:text>
</xsl:if>
</xsl:for-each>
</xsl:variable>
<xsl:template match="/*">
<xsl:apply-templates select="*[generate-id() = generate-id(key('kEleName', name()))]"/>
</xsl:template>
<xsl:template match="*">
<xsl:if test="position()=1"><xsl:text>For tags: </xsl:text></xsl:if>
<xsl:value-of select="concat(name(.), ' ', count(key('kEleName', name(.))))"/>
<xsl:if test="following-sibling::*">
<xsl:text>, </xsl:text>
</xsl:if>
<xsl:if test="position()=last()">
<xsl:text> For attributes: </xsl:text>
<xsl:value-of select="$var2"/>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
应用于您的输入时 XML
<a>
<apple color="red"/>
<apple color="green"/>
<banana color="yellow"/>
<sugar taste="sweet"/>
<cat size="small"/>
</a>
生成扩展结果:
For tags: apple 2, banana 1, sugar 1, cat 1
For attributes: color(red) 1, color(green) 1, color(yellow) 1, taste(sweet) 1, size(small) 1
更新: 如评论中所述,上述调整(以及上一个问题的答案)仅适用于问题中提供的输入。给定输入 XML,例如
<root>
<a>
<apple color="red"/>
<apple color="green"/>
<banana color="yellow"/>
<sugar taste="sweet"/>
<cat size="small"/>
</a>
<a>
<apple color="red"/>
<apple color="green"/>
<banana color="yellow"/>
<sugar taste="sweet"/>
<dog size="big"/>
</a>
</root>
模板可以调整如下:
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" omit-xml-declaration="yes"/>
<xsl:key name="kEleName" match="*" use="local-name()"/>
<xsl:key name="kAttribName" match="@*" use="local-name()"/>
<xsl:key name="kAttribValue" match="@*" use="."/>
<xsl:variable name="var1">
<xsl:for-each select="//a/*/@*[generate-id() = generate-id(key('kAttribValue', .))]">
<xsl:value-of select="concat(name(.), ' (', .,')', ' ', count(key('kAttribValue', .)))"/>
<xsl:if test="not(position()=last())">
<xsl:text>, </xsl:text>
</xsl:if>
</xsl:for-each>
</xsl:variable>
<xsl:template match="/*">
<xsl:apply-templates select="a/*[generate-id() = generate-id(key('kEleName', name()))]"/>
</xsl:template>
<xsl:template match="*">
<xsl:if test="position()=1"><xsl:text>For tags: </xsl:text></xsl:if>
<xsl:value-of select="concat(name(.), ' ', count(key('kEleName', name(.))))"/>
<xsl:if test="following::*">
<xsl:text>, </xsl:text>
</xsl:if>
<xsl:if test="position()=last()">
<xsl:text> For attributes: </xsl:text>
<xsl:value-of select="$var1"/>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
将其应用于调整后的示例输入时 XML 会生成输出:
For tags: apple 4, banana 2, sugar 2, cat 1, dog 1
For attributes: color (red) 2, color (green) 2, color (yellow) 2, taste (sweet) 2, size (small) 1, size (big) 1
调整如下:本次
<xsl:for-each select="/a/*/@*[generate-id() = generate-id(key('kAttribValue', .))]">
必须调整为
<xsl:for-each select="//a/*/@*[generate-id() = generate-id(key('kAttribValue', .))]">
否则只有第一个 a
节点的子节点的属性被匹配。
这个
<xsl:apply-templates select="*[generate-id() = generate-id(key('kEleName', name()))]"/>
必须调整为
<xsl:apply-templates select="a/*[generate-id() = generate-id(key('kEleName', name()))]"/>
否则将选择 a
标签(这将产生输出
For tags: a 2,
)。
还有这个
<xsl:if test="following-sibling::*">
<xsl:text>, </xsl:text>
</xsl:if>
必须调整为
<xsl:if test="following::*">
<xsl:text>, </xsl:text>
</xsl:if>
因为在第二个 a
节点中添加的 dog
不是 following sibling 但仍然是 following元素。
很明显,如果未知要求允许具有不同的命名父节点,则此调整将不会工作 - 作为简化的示例,它不适用于像[=这样的输入32=]
<a>
<apple color="red"/>
<apple color="green"/>
</a>
<b>
<banana color="yellow"/>
</b>
如果不同的父节点或嵌套结构,例如
<a>
<apple color="red"/>
<apple color="green"/>
<b>
<banana color="yellow"/>
</b>
</a>
也应该处理,我建议为此提出一个新问题,因为这与问题中提供的示例输入 XML 差异太大。