可以将XSLT 1.0转换用作纯XPath 1.0位置路径评估程序吗?

时间:2011-06-28 15:04:13

标签: xpath xslt

如果以下问题看似愚蠢,请抱歉,但由于我的经验不足,我不能确定这种方法的可靠性。

我正在尝试使用XSLT 1.0构建自己的XPath 1.0 位置路径评估程序。

这个想法很简单。转换接受输入xpath表达式以进行评估,然后将模板应用于所选节点。定义每种节点的模板以在输出上复制节点(以及一些更多信息)。输入文档将使用符合XSLT 1.0标准的处理器进行转换。

  • 我想从您的专业知识中了解到,这种方法是否绝对,是否采用免费且可靠方式来测试位置路径和显示所选节点集。我不是要求有人调试我的代码。我已针对各种输入文档进行了测试,看起来工作正常。我想知道从XPath的角度来看我是否遗漏了什么。

  • 这是否可以正确使用任何 XPath 1.0 位置路径

  • 这是否仅限于XPath 1.0 / XSLT 1.0?我没有看到任何通过更改其版本(显然是XSLT处理器)将模板扩展到XPath 2.0的说明。

这是应该用作XPath测试器的转换。注意:

  • 我省略了注释和pi节点的模板,以使转换不会太重,但它们目前以类似的方式进行管理。
  • 目前不需要管理名称空间。

<xsl:stylesheet 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="1.0">

    <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
    <xsl:strip-space elements="*"/>

    <xsl:param name="path-expr" select="*"/>

    <xsl:template match="/">
        <xpath-tester>
            <node-sets count="{count($path-expr)}">
                <xsl:apply-templates select="$path-expr" mode="path-expr"/>
            </node-sets>
        </xpath-tester>
    </xsl:template>

    <xsl:template match="node()|@*" mode="path-expr">
        <node-set
            position="{position()}"
            id="{generate-id()}" 
            parent-id="{name(parent::*[1])}-{generate-id(parent::*[1])}">
            <xsl:apply-templates select="." mode="output"/>
        </node-set>
    </xsl:template>

    <xsl:template match="*" mode="output">
        <xsl:attribute name="type">element</xsl:attribute>
        <node>
            <xsl:copy-of select="."/>
        </node>
    </xsl:template>

    <xsl:template match="@*" mode="output">
        <xsl:attribute name="type">attribute</xsl:attribute>
        <node>
            <xsl:copy-of select="."/>
        </node>
    </xsl:template>

    <xsl:template match="text()" mode="output"> 
        <xsl:attribute name="type">text</xsl:attribute>
        <node>
            <xsl:copy-of select="."/>
        </node>
    </xsl:template>

</xsl:stylesheet>

3 个答案:

答案 0 :(得分:2)

听起来像我的宠物项目;随便看看我的代码,它有点太大了,不能贴在这里:

http://www.flynn1179.net/xml/FullDisplayXml.xslt

它将任何XML文档转换为具有可折叠节点的html页面,并通过修改顶部附近的键的“匹配”属性,您可以为节点指定XPath,并让它生成它们的列表或突出显示它们在源头。

我在这里问了一个非常类似的问题:How can you pass in a parameter to an xslt that can be used in a xsl:key?,虽然我试图将参数应用到密钥,但这不起作用。

注意:那段代码是正在进行中的工作,它在某些地方很难看,而且我很确定有一些东西它没有正确处理,或者可以做得更好,但希望它有用。我在我的XML沙箱页面上使用它的衍生物:http://www.flynn1179.net/xml/(这也是一项正在进行中的工作,我知道其中有一些错误)

答案 1 :(得分:1)

您可能有兴趣查看我11岁 XPath Vizualizer 的代码。

在XSLT 2.0中不直接支持XSLT内部的动态评估,并且在XSLT 3.0 / XPath 3.0中可能存在这样的支持,这根本不是必需的。

答案 2 :(得分:0)

首先@Martin指出

  

您需要支持动态XPath评估才能将XPath作为节点集处理

为了处理动态XPath评估,我对转换进行了一些扩展。转换现在能够接受输入字符串并将其评估为XPath。

现在使用saxon:evaluate依赖萨克森。以类似的方式并且在function-available的支持下,可以实现其他扩展并使其更加便携。

这里有三个新模板(以及两个新参数)替换原始转换中的根模板(给定命名空间声明xmlns:saxon="http://icl.com/saxon")。

    <xsl:param name="path-expr" select="false()"/>
    <xsl:param name="xpath" select="*"/>

    <xsl:template match="/">
        <xsl:choose>
            <xsl:when test="$path-expr">
                <xsl:apply-templates select="/" mode="dyn"/>
            </xsl:when>
            <xsl:otherwise>
                <xsl:apply-templates select="/" mode="base"/>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>

    <xsl:template match="/" mode="dyn">
        <xpath-tester>
            <node-sets count="{count(saxon:evaluate($path-expr))}">
                <xsl:apply-templates select="saxon:evaluate($path-expr)" 
                    mode="path-expr"/>
            </node-sets>
        </xpath-tester>
    </xsl:template>

    <xsl:template match="/" mode="base">
        <xpath-tester>
            <node-sets count="{count($xpath)}">
                <xsl:apply-templates select="$xpath" 
                  mode="path-expr"/>
            </node-sets>
        </xpath-tester>
    </xsl:template>

第二个@Martin指出

  

我怀疑你一起输出属性和元素节点会遇到麻烦

我已经进行了测试并遇到了这个问题,但是如上所述,即使在那种情况下也能正常工作。