在 XSLT 1.0 中,如何使用 key 和 document('') 对嵌入 XSLT 中的 XML 数据创建查找函数?

问题描述 投票:0回答:2

我的具体需求是查找给定特定字体大小的行高,但我正在寻求学习创建查找/特定映射的通用技术。

我认为可以将 XML 嵌入到 XSLT 文档本身中(这样它就可以独立工作)并使用 document('') 函数在其上构建一个键来引用当前的 XSLT,如下所示:

<xsl:variable name="data.font-metrics.line-height">
    <line-height font-size="11">12</line-height>
    <line-height font-size="12">14</line-height>
    <line-height font-size="13">15</line-height>
    <line-height font-size="14">16</line-height>
    <line-height font-size="15">17</line-height>
    <line-height font-size="16">18</line-height>
    <line-height font-size="17">20</line-height>
    <line-height font-size="18">21</line-height>
</xsl:variable>
<xsl:key name="lookup.font-metrics.line-height" match="document('')//xsl:variable[@name='data.font-metrics.line-height'])/line-height" use="@font-size"/>

之后,我应该能够使用 key 函数查找行高:

<xsl:value-of select="key('lookup.font-metrics.line-height',$font-size)"/>

...但是我收到以下错误消息:

XPath error : Invalid expression
//document('')//xsl:variable[@name='data.font-metrics.line-height'])/line-height/text()
           ^

我认为这里有几个问题:

  • 文档功能的使用
  • 按键功能的使用
  • 嵌入 XML 的最佳方法是什么?在变量中?

问题也可能有完全不同的解决方案。

我将非常感谢您的帮助!

xslt key document lookup xpath-1.0
2个回答
2
投票

在 XSLT 1.0 中,

key()
函数仅在当前文档的上下文中起作用(在 XSLT 2.0 中,它有第三个参数,允许您选择上下文)。为了在另一个文档中的节点上使用密钥,您必须首先将上下文切换到该文档 - 例如:

XSLT 1.0

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

<xsl:variable name="data.font-metrics.line-height">
    <line-height font-size="11">12</line-height>
    <line-height font-size="12">14</line-height>
    <line-height font-size="13">15</line-height>
    <line-height font-size="14">16</line-height>
    <line-height font-size="15">17</line-height>
    <line-height font-size="16">18</line-height>
    <line-height font-size="17">20</line-height>
    <line-height font-size="18">21</line-height>
</xsl:variable>

<xsl:key name="lookup.font-metrics.line-height" match="line-height" use="@font-size"/>

<xsl:template match="/">
    <xsl:param name="font-size" select="14"/>
    <output>
        <!-- other nodes -->
        <!-- switch context to the stylesheet itself in order to use the key -->
        <xsl:for-each select="document('')">
            <lookup>
                <xsl:value-of select="key('lookup.font-metrics.line-height', $font-size)"/>
            </lookup>
        </xsl:for-each>
        <!-- more nodes -->
    </output>
</xsl:template>

</xsl:stylesheet>

结果

<?xml version="1.0" encoding="UTF-8"?>
<output>
   <lookup>16</lookup>
</output>

请注意,

xsl:key
元素在此开关中不发挥作用,可以用更简单的术语进行定义。


0
投票

这意味着,当 XSLT 引擎首次到达键定义元素时,而不是当 XSLT 引擎遇到

第一个 
XPath key() 函数时,<xsl:key> 不会(匹配和)编译。只有此时才能创建密钥,因为只有此时上下文才已知。

...一种懒惰的执行...

此外,一个键可以应用于多个文档,因此如果要转换的 XML 文档包含以下 XML:

<?xml version="1.0" encoding="UTF-8"?>
<fmxmlsnippet type="LayoutObjectList">
    <Layout enclosingRectTop ="46.0000000" enclosingRectLeft ="46.0000000" enclosingRectBottom ="171.0000000" enclosingRectRight ="366.0000000">
        <line-height font-size="14">18 in XML file</line-height>
        …

然后是以下 XSLT(添加到上面的原始 XSLT 中):

    <xsl:comment>
        <xsl:for-each select="document('')">
            <!-- apply the key to the XSLT document -->
            <xsl:value-of select="key('lookup.font-metrics.line-height','14')"/>
        </xsl:for-each>
    </xsl:comment>
    <xsl:comment>
            <!-- apply the key to the XML document -->
            <xsl:value-of select="key('lookup.font-metrics.line-height','14')"/>
    </xsl:comment>

将创建以下输出:

<!--16-->
<!--18 in XML file-->

因此,关键函数不是对先前构建的静态索引的引用,而是 - 与 for-each-document('') 技巧相结合 - 正是我正在寻找的:一个可以在 XML 节点上使用的查找函数,无论他们在哪里!

很好。

© www.soinside.com 2019 - 2024. All rights reserved.