XSL 动态 XPath 评估

Posted

技术标签:

【中文标题】XSL 动态 XPath 评估【英文标题】:XSL Dynamic XPath evaluation 【发布时间】:2021-10-03 16:27:45 【问题描述】:
<name>
  <pattern>/Book/Title</pattern>
  <pattern>/Newspaper/Title</pattern>
</name>
<Description>
  <pattern>/Book/Descriptions/*</pattern>
  <pattern>/Newspaper/Descriptions/*<pattern>
</Description>

我有一组不同的 XML 文件。给定一个像上面这样的 XML 文件,我想从所有这些文件中提取语义相似的信息,并以 JSON 格式显示。例如。我可能想从其中一个 XML 编码书籍信息中提取名称和描述,以接收如下文件:

 "name": "Harry Potter",
 "description": ["DescA", "DescB"]

所属的 XML 文件可能如下所示:

<Book>
  <Title>Harry Potter</Title>
  <Author>J.K. Rowling </Author>
  <Description lang="de">DescA</Description>
  <Description lang="en">DescB</Description>
</Book>

我曾想过使用 XSL 3.0 来使用 xsl:evaluate 函数,但它没有按我预期的方式工作。

使用类似 sn-p 的代码:

<xsl:variable name="pattern">
   <xsl:evaluate xpath="/Book/Descriptions/*" context-item="$root"/>
</xsl:variable>
<xsl:for-each select="$pattern">
    <xsl:value-of select="."/>
    <xsl:text>,</xsl:text>
</xsl:for-each>

我只将所有描述作为一个长连接字符串,而不是能够循环遍历它们。我本来期望像“DescA,DescB”这样的输出,但只会得到“DescADescB”。 我对 XSL 很陌生,因此不胜感激。无论是如何以更有效的方式设计上述映射,还是如何以这种方式使用评估函数,我都可以获得单独的描述。 有关信息,目前正在使用带有 Java 的 Saxon XSL HE 10.5。

【问题讨论】:

如果您需要带有xsl:evaluate 的变量,也许可以将正确的as="item()*" 放在您的xsl:variable 上。对于整个问题,重现事物的最小但完整的样本会有所帮助。 这些答案有帮助吗? 【参考方案1】:

从简单开始,例如

  <xsl:template match="/">
    <xsl:value-of separator=",">
      <xsl:evaluate xpath="'Book/Description'" context-item="."/>
    </xsl:value-of>
  </xsl:template>

对于您的示例,

<Book>
  <Title>Harry Potter</Title>
  <Author>J.K. Rowling </Author>
  <Description lang="de">DescA</Description>
  <Description lang="en">DescB</Description>
</Book>

应该给DescA,DescB

存储在 xsl:variable 元素内构造的项目序列,例如xsl:evaluate 作为项目序列而不是结果树的子节点是通过使用例如实现的。 xsl:variable as="item()*" ...,而不是通过更改您的 xsl:evaluate

【讨论】:

谢谢,item()* 成功了。您是否也碰巧知道在哪里可以找到可用于“as”的所有可能类型? @DerMannMitDerMaske,如果您想阅读规范,那么 w3.org/TR/xpath-31/#doc-xpath31-SequenceType 可以提供帮助,我希望在任何 XSLT/XPath 2 或更高版本的教科书中对类型系统有更易读的描述和解释. 谢谢,我去看看。【参考方案2】:

我有点困惑,因为这里有两个 XML 文档,它们都包含匹配 Description 的元素,但都没有匹配 Book/Descriptions/* 的元素,而一个包含模式(表达式)的被评估不包含 Book 元素。

也许您真正的错误被复制/粘贴错误所掩盖。您选择的变量名pattern 也暗示您可能会感到困惑:xsl:evaluate 的结果不是模式(甚至不是 XPath 表达式),它是一组节点。

一个明确的错误是您没有在变量上指定as 属性(这意味着 xsl:evaluate 的结果被复制到新的文档树中)。我希望是这样的:

<xsl:variable name="selected-nodes" as="node()*">
   <xsl:evaluate xpath="//Description/pattern" context-item="$root"/>
</xsl:variable>

但我不确定这正是您想要的,因为//Description/pattern 选择了多个表达式,而xsl:evaluate 只会评估一个。如果你想评估多个模式并组合结果,那是可以做到的,但我需要更清楚地理解需求。

【讨论】:

以上是关于XSL 动态 XPath 评估的主要内容,如果未能解决你的问题,请参考以下文章

流式 XPath 评估

xslt 中的 xpath 产生与直接评估 xpath 不同的结果

XPath 是不是对逻辑表达式进行短路评估?

xpath 文档评估包含此 OR

优化 xslt xpath 匹配表达式

在python中评估Xpath2.0