我有一个输入XML,如下所示:
<?xml version="1.0" encoding="UTF-8"?>
<Root>
<Rules>
<Rule ruleName="Rule1" ruleType="A"/>
<Rule ruleName="Rule2" ruleType="B"/>
<Rule ruleName="Rule3" ruleType="C"/>
</Rules>
<Description>
<Rule1>My description for rule 1</Rule1>
<Rule2>My description for rule 2</Rule2>
<Rule3>My description for rule 3</Rule3>
</Description>
</Root>
我需要通过XSLT将其转换为如下结构:
<?xml version="1.0" encoding="UTF-8"?>
<Root>
<Rules>
<Rule ruleName="Rule1" ruleType="A"/>
<Description>My description for rule 1</Description>
</Rule>
<Rule ruleName="Rule2" ruleType="B"/>
<Description>My description for rule 2</Description>
</Rule>
<Rule ruleName="Rule3" ruleType="C">
<Description>My description for rule 3</Description>
</Rule>
</Rules>
</Root>
这意味着对于每个 / Root / Rules / Rule 节点,我必须根据< / Root / Description / Rule?节点选择值< em> / Root / Rules / Rule / @ ruleName 值。 / Root / Rules / Rule 和 / Root / Description / Rule?的顺序是随机的。
我已经创建了一个模板来处理 / Root / Rules / Rule 节点,但我无法弄清楚如何编写一个xpath,因为“从 / Root中选择节点值/ Description 其中节点名称等于 ./@ ruleName “。我有什么想法或程序可以实现它吗?
答案 0 :(得分:2)
使用name="ref" match="Description/*" use="local-name()"
定义密钥,然后您可以使用key('ref', @ruleName)
查找Description元素。请参阅https://www.w3.org/TR/xslt#key。
作为替代方案,您可以使用current()
(https://www.w3.org/TR/xslt#function-current)来编写相对于当前匹配节点的XPath表达式,即使用
<xsl:template match="/Root/Rules/Rule">
<xsl:copy>
<xsl:copy-of select="@*"/>
<Description>
<xsl:value-of select="/Root/Description/*[local-name() = current()/@ruleName]"/>
</Description>
</xsl:copy>
</xsl:template>
您获得与密钥相同的结果。考虑阅读密钥,然而,在XSLT中有效地遵循交叉引用是一个基本概念。
答案 1 :(得分:2)
虽然我更喜欢Martin的解决方案,但请参阅以下解决方案,将规则名称存储在变量中,然后在XPath表达式中使用它:
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="/">
<xsl:apply-templates select = "Root/Rules/*"/>
</xsl:template>
<xsl:template match="Rule">
<xsl:variable name="rulename" select="@ruleName"/>
<xsl:element name="Rule">
<xsl:copy-of select="@*"/>
<xsl:element name="Description">
<xsl:copy-of select="/Root/Description/*[local-name() = $rulename]/text()"/>
</xsl:element>
</xsl:element>
</xsl:template>
</xsl:stylesheet>