【问题标题】:Looking for saxon:evaluate() example code寻找 saxon:evaluate() 示例代码
【发布时间】:2018-12-13 10:53:13
【问题描述】:

我有一个将处理 input.xml 的 transform.xsl 文件。但还有一个额外的 config.xml 文件将定义额外的子句。例如这是 config.xml 的内容。

<Location >
  <DisplayName>
     <Attribute1>ABC</Attribute1>
     <Attribute2>XYZ</Attribute2>
     <action>concat($Attribute1,$Attribute2)</action>
  </DisplayName>
</Location >

所以当transform.xsl 遇到input.xml 中的DisplayName 变量时,它会用config.xml 文件中定义的动作表达式的RESULT 形成值。 transform.xml 将调用 config.xml 只是为了得到结果。 (最终用户可以修改该操作,因此这些操作位于 xsl 文件之外的 config.xml 中)。

我们使用的是 saxon xml 处理器版本 9 和 xslt 2.0。所以我们需要使用 saxon:evaluate()。我试图找到更多 saxon:evaluate() 的示例,但找不到更多。谁能告诉我一些如何使用它的例子?

提前致谢。

***** 这是一个经过编辑的查询,突出了撒克逊人的需要:评估 *****

【问题讨论】:

  • 我在regex 属性中看不到任何正则表达式,相反,它似乎是一个XPath 表达式,对concat 函数的调用,其中两个变量或参数引用作为@987654325 的参数@。目前尚不清楚为什么您需要它,而不是仅在样式表或单独的样式表模块中使用普通参数或变量,但一般来说,如果您需要一些动态评估或代码生成和执行,那么迁移到 XSLT 3 可以帮助您有各种选项,如阴影属性、transform 函数加上 xsl:evaluate(如果支持)来解决此类问题。
  • 嗨@MartinHonnen:感谢您的回复。用例是当在 input.xml 中搜索 Location 元素时,它的 DisplayName 将来自 config.xml 文件的 regex 元素。我认为我们需要选择xsl:evaluate,这是唯一的方法,Saxon 支持这一点。但是,如果我使用 &lt;xsl:template match="/"&gt; &lt;xsl:message&gt; VALUE is = &lt;xsl:value-of select="saxon:evaluate($regex)"/&gt; &lt;/xsl:message&gt; &lt;/xsl:template&gt;,我会收到以下错误 - 提供给 saxon 的 XPath 表达式中的静态错误:评估:XPath 表达式中未声明的变量:$Attribute1
  • 您使用的是哪个版本的撒克逊语?您已将您的问题标记为 xslt-2.0,Saxon 因为 9.8 支持 XSLT 3.0,并且我们有 xsl:evaluate 元素。在早期版本中,支持扩展函数 saxon:evaluate
  • 我看不到任何情况下您会选择使用最新版本的 Saxon 并且更喜欢 saxon:evaluate 而不是 xsl:evaluate。尽管您说您使用的是 XSLT 2.0,但使用 XSLT 3.0 中标准化的特性一定比使用专有的 Saxon 扩展更好,因为两者都在您选择的处理器中可用。在任何情况下,xsl;evaluate 都满足这一要求(允许使用任何名称的变量),而 saxon:evaluate 则不满足(变量必须命名为 $p1、$p2 等)。

标签: xslt-2.0 saxon


【解决方案1】:

以下是使用支持xsl:evaluate (https://www.w3.org/TR/xslt-30/#dynamic-xpath) 的 XSLT 3 处理器(即商业 PE 或 EE 版本的 Saxon 9.8 或更高版本或 Altova 2017 或更高版本)处理“配置”文件的示例:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:map="http://www.w3.org/2005/xpath-functions/map"
    xmlns:mf="http://example.com/mf"
    exclude-result-prefixes="#all"
    version="3.0">

    <xsl:param name="config-url" as="xs:string">test2018121301.xml</xsl:param>
    <xsl:param name="config-doc" select="doc($config-url)"/>

    <xsl:mode on-no-match="shallow-copy"/>

    <xsl:key name="element" match="*" use="node-name()"/>

    <xsl:function name="mf:config-evaluation" as="item()*">
        <xsl:param name="config-doc" as="document-node()"/>
        <xsl:param name="element-name" as="xs:QName"/>
        <xsl:variable name="display" select="key('element', $element-name, $config-doc)/DisplayName"/>
        <xsl:evaluate xpath="$display/regex" with-params="map:merge($display!(* except regex)!map { QName('', local-name()) : string() })"/>
    </xsl:function>

    <xsl:template match="*[key('element', node-name(), $config-doc)]">
        <xsl:copy>
            <xsl:value-of select="mf:config-evaluation($config-doc, node-name()), ."/>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

所以使用 config.xml

<Location >
    <DisplayName>
        <Attribute1>ABC</Attribute1>
        <Attribute2>XYZ</Attribute2>
        <regex>concat($Attribute1,$Attribute2)</regex>
    </DisplayName>
</Location >

这将使用例如转换输入样本

<Root>
    <Items>
        <Item>
            <Data>data 1</Data>
            <Location>location 1</Location>
        </Item>
        <Item>
            <Data>data 2</Data>
            <Location>location 2</Location>
        </Item>
    </Items>
</Root>

进入

<Root>
    <Items>
        <Item>
            <Data>data 1</Data>
            <Location>ABCXYZ location 1</Location>
        </Item>
        <Item>
            <Data>data 2</Data>
            <Location>ABCXYZ location 2</Location>
        </Item>
    </Items>
</Root>

这为您在配置文件中允许 XPath 表达式提供了极大的灵活性,但正如 https://www.w3.org/TR/xslt-30/#evaluate-effect 中指出的那样,这也是一个安全问题:“样式表作者需要了解与使用 xsl 相关的安全风险:评估。该指令不应用于执行来自不受信任源的代码。"。

至于使用旧版Saxon支持的saxon:evaluate函数不支持XSLT 3 xsl:evaluate指令,一个简单的例子是

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:saxon="http://saxon.sf.net/"
    exclude-result-prefixes="#all"
    version="2.0">

    <xsl:template match="@* | node()">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="example">
        <xsl:copy>
            <xsl:value-of select="saxon:evaluate(@expression, @foo, @bar)"/>
        </xsl:copy>
    </xsl:template>   

</xsl:stylesheet>

转换输入

<root>
    <example expression="concat($p1, $p2)" foo="This is " bar="an example."/>
    <example expression="replace(., $p1, $p2)" foo="\p{L}" bar="X">This is example 2.</example>
</root>

进入结果

<root>
    <example>This is an example.</example>
    <example>XXXX XX XXXXXXX 2.</example>
</root>

【讨论】:

  • 嗨 Martin,我们正在使用 XSLT 2.0,我在上面的评论中提到了 saxon:evaluate。你有相同的示例代码吗?我搜索了很多,但找不到任何东西。
  • saxonica.com/html/documentation9.7/functions/saxon/…有文档,看来要用的参数需要命名为p1p2等。我相信如果您编辑您的问题并添加 saxon 并提供有关您使用的 Saxon 版本的准确信息,您将直接从 Saxonica/Michael Kay 获得有关如何使用该扩展功能的帮助。
  • @NirmalyaSinha,我添加了一个简单的示例,展示了如何使用saxon:evaluate。在您最初的问题的上下文中,我不确定它是否有用,除非您可以确保您使用的 XPath 表达式使用名为 $p1, $p2, ... 的参数引用。
【解决方案2】:

尝试检查xsl-attribute 标记和xsl-value-of 标记。如果我得到您的要求,您可能可以使用 transform.xsl(或中间文件的第二个 xsl)读取 config.xml,以将正则表达式标签内的文本设置为对应于标签属性的值在 xsl 中。

https://www.w3schools.com/xml/ref_xsl_el_attribute.asp

另外,请查看本教程以了解 XSLT 2 中的正则表达式,它可能会有所帮助:

https://www.xml.com/pub/a/2003/06/04/tr.html

【讨论】:

    猜你喜欢
    • 2018-06-30
    • 1970-01-01
    • 2023-03-13
    • 2010-09-16
    • 1970-01-01
    • 1970-01-01
    • 2021-05-03
    • 1970-01-01
    • 2010-12-04
    相关资源
    最近更新 更多