我需要根据ID号搜索一系列元素。如果找到了ID号,我会处理它。如果找不到ID,则会使用默认值填写。我在Saxon 9.4 HE中使用XSLT 2.0。
这是一个非常简化的例子。输入XML如下所示:
<root>
<item>
<id>1</id>
</item>
<item>
<id>2</id>
</item>
<item>
<id>4</id>
</item>
</root>
如果我正在搜索ID为1,2或3的项目,我想获得以下输出。请注意,我不希望第4项有任何输出。
Found 1
Found 2
Didn't find 3
我的第一次尝试是使用for-each循环,但它甚至没有编译。我得到的错误是“XPTY0020:Axis step child :: element('':id)不能在这里使用:上下文项是一个原子值”从行“”。
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:variable name="ids" select="(1, 2, 3)"/>
<xsl:template match="/root">
<xsl:for-each select="$ids">
<xsl:choose>
<xsl:when test="count(item/id = .) > 0">
Found <xsl:value-of select="."/>
</xsl:when>
<xsl:otherwise>
Didn't find <xsl:value-of select="."/>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
之后我意识到我可以很容易地找到匹配的以下内容,但我无法找到找到遗漏的方法。
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:variable name="ids" select="(1, 2, 3)"/>
<xsl:template match="/">
<xsl:apply-templates select="root/item[id=$ids]"/>
</xsl:template>
<xsl:template match="item">
Found <xsl:value-of select="id"/>
</xsl:template>
</xsl:stylesheet>
顺便说一句,输出也需要按ID排序,这意味着转储所有找到的项目的列表,然后列出未找到的项目列表将不起作用。这是否可能,或者我应该采取轻松/懦弱的道路并改变我的意见?
答案 0 :(得分:1)
以下是一个例子:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:key name="k1" match="item" use="number(id)"/>
<xsl:param name="ids" select="(1, 2, 3)"/>
<xsl:template match="/">
<xsl:variable name="root" select="."/>
<xsl:for-each select="$ids">
<xsl:choose>
<xsl:when test="key('k1', ., $root)">
<xsl:text>Found </xsl:text>
<xsl:value-of select="."/>
</xsl:when>
<xsl:otherwise>
<xsl:text>Didn't find </xsl:text>
<xsl:value-of select="."/>
</xsl:otherwise>
</xsl:choose>
<xsl:text> </xsl:text>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
[编辑] 你的初始尝试是正确的,因为处理id序列是有关的,但你需要将主输入文档存储在for-each之外,因为在上下文项中是一个id号值而没有外部变量你不会能够访问文档中的项目元素。
为了提高效率,我添加了密钥。
答案 1 :(得分:1)
这是一个更简单(没有明确的条件)和更短的解决方案:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xsl:output method="text"/>
<xsl:key name="kIdByVal" match="id" use="."/>
<xsl:param name="psortedIds" as="xs:string+"
select="'1','2','3'"/>
<xsl:variable name="vDoc" select="/"/>
<xsl:template match="/*">
<xsl:for-each select="$psortedIds">
<xsl:sequence select=
'("found ", "didn't find ")
[2 - number(boolean(key("kIdByVal", current(), $vDoc)))],
., "
"
'/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
在提供的XML文档上应用此XSLT 2.0转换:
<root>
<item>
<id>1</id>
</item>
<item>
<id>2</id>
</item>
<item>
<id>4</id>
</item>
</root>
产生了想要的正确结果:
found 1
found 2
didn't find 3