问题描述
人,
<root>
<concepts>
<concept id="1" version="1">
<name>This is the name of 1.1</name>
</concept>
<concept id="1" version="2">
<name>This is the name of 1.2</name>
</concept>
<concept id="2" version="1">
<name>This is the name of 2.1</name>
</concept>
</concepts>
<structures>
<structure id="1">
<conceptRef id="2" version="1" />
</structure>
<structure id="2">
<conceptRef id="1" version="2" />
</structure>
</structures>
</root>
我想根据结构/概念引用子节点中的属性值获取概念的名称子节点中的文本。上面例子的输出应该是这样的:
所以我目前有这样的事情:
<xsl:template match="structures">
<xsl:for-each select=".//structure">
Structure <xsl:value-of select="@id" />: <!-- Todo: what goes here -->
</xsl:for-each>
</xsl:template>
我不知道的是,我如何嵌套 XPath 查询以根据当前上下文从其他树中查找节点。出于调试目的,我现在添加了三个不同的行来测试该方法:
<xsl:template match="structures">
<xsl:for-each select=".//structure">
Structure <xsl:value-of select="@id" />:
0: <xsl:value-of select="./conceptRef/@id" />.<xsl:value-of select="./conceptRef/@version" />
a: <xsl:value-of select="//concepts/concept[@id=./conceptRef/@id and @version=./conceptRef/@version]/name" />
b: <xsl:value-of select="//concepts/concept[@id=1 and @version=2]/name" />
</xsl:for-each>
</xsl:template>
输出为:
Structure 1:
0: 2.1
a:
b: This is the name of 1.2
Structure 2:
0: 1.2
a:
b: This is the name of 1.2
这意味着小于 0 的值会为过滤器提供正确的值。在第 2 行中,我看到了同样有效的硬编码值。就在我将两者在 a 行中合并时,结果由于某种原因为空。
有什么想法吗?
谢谢, 丹尼尔。
解决方法
我强烈建议使用 key 来解决交叉引用。以下样式表:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" encoding="UTF-8"/>
<xsl:key name="concept" match="concept" use="concat(@id,'|',@version)" />
<xsl:template match="/root">
<xsl:for-each select="structures/structure">
<xsl:text>Structure </xsl:text>
<xsl:value-of select="@id" />
<xsl:text>: </xsl:text>
<xsl:value-of select="key('concept',concat(conceptRef/@id,conceptRef/@version))/name" />
<xsl:text> </xsl:text>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
应用于您的输入示例,将产生:
结果
Structure 1: This is the name of 2.1
Structure 2: This is the name of 1.2
,
您想使用 current()
函数,例如//concepts/concept[@id=current()/conceptRef/@id and @version=current()/conceptRef/@version]/name
为您的工作路径。为了提高效率,您可能希望通过声明一个键并使用键函数来替换该查找。