【问题标题】:Check if string exists in array of strings XSL检查字符串XSL数组中是否存在字符串
【发布时间】:2015-01-20 20:39:08
【问题描述】:

在 XSL 中是否可以检查字符串是否存在于字符串数组中? 我有以下 XML:

<?xml version="1.0" encoding="UTF-8"?>
<ItemsArr>
  <it attr="DANCHO">
    <title>1</title>
  </it>
  <it attr="DAN">
    <title>2</title>
  </it>
  <it attr="IVANCHO">
    <title>3</title>
  </it>
  <it attr="DRAGANCHO">
    <title>4</title>
  </it>
  <it attr="PETKANCHO">
    <title>5</title>
  </it>
  <keys>
    <itemKey>DANCHO</itemKey>
    <itemKey>THISISONLYFORTESTING</itemKey>
  </keys>
</ItemsArr>

以及以下 XSL 转换:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
  <html>
  <body>
    <table border="1">
    <xsl:variable name="items" select="ItemsArr/keys/itemKey"/>

    <xsl:for-each select="/ItemsArr/it[contains($items,@attr)]">
     <tr>
        <td><xsl:value-of select="@attr"/></td>
        <td><xsl:value-of select="title"/></td>
      </tr>
    </xsl:for-each>
    </table>

  </body>
  </html>
</xsl:template>
</xsl:stylesheet>

我想将所有键 (ItemsArr/Keys) 存储在一个数组 ($items) 中,然后遍历 it-s,该 attr 值存在于 $items 数组中。 请注意,对于上述数据,两者都被选中。 如果交换了两个键(DANCHO 和 THISISONLYFORTESTING),则不会选择任何内容。

【问题讨论】:

    标签: arrays xml xslt


    【解决方案1】:

    contains 实际上是一个字符串函数,它检查第一个字符串是否“包含”第二个字符串。它不适用于节点集(在 XSLT 1.0 中,如果您将节点集传递给它,它将获得该集中第一个节点的文本值。在 XSLT 2.0 中,它会出错)。

    您可以使用的表达式就是这样...

    <xsl:for-each select="/ItemsArr/it[@attr = $items/text()]">
    

    因此,如果attr 属性与节点集中任何项目的文本节点匹配,则为真。

    或者,考虑使用键更有效地查找值。

    <xsl:key name="items" match="itemKey" use="text()" />
    

    然后你会像这样查找它

    <xsl:for-each select="/ItemsArr/it[key('items', @attr)]">
    

    试试这个 XSLT

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:key name="items" match="itemKey" use="text()" />
    
    <xsl:template match="/">
      <html>
      <body>
        <table border="1">
        <xsl:variable name="items" select="ItemsArr/keys/itemKey"/>
    
        <xsl:for-each select="/ItemsArr/it[key('items', @attr)]">
         <tr>
            <td><xsl:value-of select="@attr"/></td>
            <td><xsl:value-of select="title"/></td>
          </tr>
        </xsl:for-each>
        </table>
    
      </body>
      </html>
    </xsl:template>
    </xsl:stylesheet>
    

    【讨论】:

    • 这正是我所需要的!愚蠢的我......我是 XSL 的新手,你帮了我很多。我会坚持你提供的第一个解决方案。
    【解决方案2】:

    您应该陈述您的问题,而不是您认为要如何解决它,因为 XSLT 1 或 2 中没有数组数据结构。

    如果您的问题是实现一个数据结构,您可以查找 xsl:key 的用途。所以你应该阅读 xsl:key 和 key 函数。

    然后在你的代码中 key("array",pathToLookupValue) 会告诉你你提供的路径中的值是否存在于你设置的键中。

    【讨论】:

      【解决方案3】:

      我知道以下内容不是对这个问题的直接回答,因为我怀疑希望为此目的应用原生 XSLT 构造。但是,我可以说我通过引入基于 Saxon XSLT 处理器支持的 Java 代码的扩展函数 (https://www.saxonica.com/html/documentation/extensibility/integratedfunctions/) 解决了类似的问题。您也可以在 .NET 中使用 Saxon 或内置 .NET XSLT 处理器、使用 Python XSLT 处理器或您选择的任何支持扩展功能的 XSLT 处理器来执行相同的操作。

      我编写的函数需要三个参数:1) 分隔符(例如逗号),2) 由分隔符分隔的字符串,3) 表示查询内容的字符串。如果我们假设函数名为“contains”,则应用该函数的示例是:“contains(“1,2,3,6”, “,”, “3”)’。 或者,XSLT 2.0 及更高版本支持定义这样的函数,因此这是另一种方法。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-12-27
        • 2020-07-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-31
        • 1970-01-01
        相关资源
        最近更新 更多