2

我需要根据 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) cannot be used here: context item is an atomic value”来自“”行。

<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 排序,这意味着转储所有找到的项目的列表,然后再转储未找到的项目的列表是行不通的。这甚至可能吗,还是我应该走轻松/懦弱的道路并改变我的输入?

4

2 回答 2

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>&#10;</xsl:text>
    </xsl:for-each>
</xsl:template> 

</xsl:stylesheet>

[编辑]您的初始尝试对于处理 id 序列是正确的,但是您需要将主输入文档存储在 for-each 之外,因为上下文项内部是一个 id 数字值并且没有外部变量将无法访问文档中的项目元素。

为了提高效率,我添加了密钥。

于 2012-03-11T19:06:19.787 回答
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&apos;t find ")
       [2 - number(boolean(key("kIdByVal", current(), $vDoc)))],
    ., "&#xA;"
   '/>
  </xsl:for-each>
 </xsl:template>
</xsl:stylesheet>

当此 XSLT 2.0 转换应用于提供的 XML 文档时

<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 
于 2012-03-16T03:28:28.237 回答