Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/xpath/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
xslt命名模板:如何编写模板来创建表示给定节点xpath的字符串_Xslt_Xpath - Fatal编程技术网

xslt命名模板:如何编写模板来创建表示给定节点xpath的字符串

xslt命名模板:如何编写模板来创建表示给定节点xpath的字符串,xslt,xpath,Xslt,Xpath,我正在尝试编写一个递归命名模板,该模板将显示给定节点的路径: <?xml version="1.0"?> <testfile> <section> <title>My Section</title> <para>Trying to write a recursive function that will return a basic xpath of a given node; in

我正在尝试编写一个递归命名模板,该模板将显示给定节点的路径:

<?xml version="1.0"?>

<testfile>
    <section>
        <title>My Section</title>
        <para>Trying to write a recursive function that will return a basic xpath of a given node; in the case of this node, I would want to return testfile/section/para, I don't need /testfile/section[1]/para[1] or anything like that. The issue I'm having is that in the case of a named template, I don't know how to select a different node and apply it to the named template.</para>

    </section>

</testfile>
等等


我肯定我错过了一些简单的东西……谢谢。

我想你想要这样的东西:

<xsl:variable name="get.path">
    <xsl:text> /</xsl:text>
    <xsl:for-each select="ancestor-or-self::*">
        <xsl:variable name="get.current.node" select="name(.)"/>
        <xsl:value-of select="name()"/>
        <xsl:text>[</xsl:text>
        <xsl:value-of select="count(preceding-sibling::*[name(.) = $get.current.node]) + 1"/>
        <xsl:text>]</xsl:text>
        <xsl:if test="position() != last()">
            <xsl:text>/</xsl:text>
        </xsl:if>
    </xsl:for-each>
</xsl:variable>

/
[
]
/

我想你想要这样的东西:

<xsl:variable name="get.path">
    <xsl:text> /</xsl:text>
    <xsl:for-each select="ancestor-or-self::*">
        <xsl:variable name="get.current.node" select="name(.)"/>
        <xsl:value-of select="name()"/>
        <xsl:text>[</xsl:text>
        <xsl:value-of select="count(preceding-sibling::*[name(.) = $get.current.node]) + 1"/>
        <xsl:text>]</xsl:text>
        <xsl:if test="position() != last()">
            <xsl:text>/</xsl:text>
        </xsl:if>
    </xsl:for-each>
</xsl:variable>

/
[
]
/

您确实可以将节点作为参数传递给模板

<xsl:template name="getXpath">
<xsl:param name="pathText"/>
<xsl:param name="node" select="." />

要对其应用轴,例如测试祖先,您可以执行以下操作

<xsl:when test="$node/ancestor::*">

要在递归调用模板时将其父元素传递给模板,请执行以下操作:

<xsl:with-param name="node" select="$node/parent::*" />

试试这个XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml"/>
<xsl:template match="/">
    <result>
        <xsl:apply-templates/>
    </result>
</xsl:template>

<xsl:template match="*">
    <xsl:variable name="xpath">
        <xsl:call-template name="getXpath">
            <xsl:with-param name="pathText" select="''"/>
        </xsl:call-template>
    </xsl:variable>

    <element>element name : <xsl:value-of select="name()"/> path : <xsl:value-of select="$xpath"/></element>
    <xsl:apply-templates/>
</xsl:template>

<xsl:template name="getXpath">
<xsl:param name="pathText"/>
<xsl:param name="node" select="." />

<xsl:message>top of get xpath func path text : <xsl:value-of select="$pathText"/>    </xsl:message>
    <xsl:choose>
        <xsl:when test="$node/ancestor::*">
            <xsl:message><xsl:value-of select="name($node)"/> has a parent</xsl:message>
            <xsl:call-template name="getXpath">
                <xsl:with-param name="pathText">
                    <xsl:value-of select="name($node)"/>    <xsl:text>/</xsl:text><xsl:value-of select="$pathText"/>
                </xsl:with-param>   
                <xsl:with-param name="node" select="$node/parent::*" />
            </xsl:call-template>
        </xsl:when>
        <xsl:otherwise>
            <xsl:message><xsl:value-of select="name($node)"/> has no parent!</xsl:message>
            <xsl:value-of select="$pathText"/>
        </xsl:otherwise>
    </xsl:choose>   
</xsl:template>
</xsl:stylesheet>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml"/>
<xsl:template match="/">
    <result>
        <xsl:apply-templates/>
    </result>
</xsl:template>

<xsl:template match="*">
    <xsl:variable name="xpath">
        <xsl:apply-templates select="." mode="getXpath">
            <xsl:with-param name="pathText" select="''"/>
        </xsl:apply-templates>
    </xsl:variable>

    <element>element name : <xsl:value-of select="name()"/> path : <xsl:value-of select="$xpath"/></element>
    <xsl:apply-templates/>
</xsl:template>

<xsl:template match="*" mode="getXpath">
<xsl:param name="pathText"/>
<xsl:message>top of get xpath func path text : <xsl:value-of select="$pathText"/>    </xsl:message>
    <xsl:choose>
        <xsl:when test="ancestor::*">
            <xsl:message><xsl:value-of select="name()"/> has a parent</xsl:message>
            <xsl:apply-templates select=".." mode="getXpath">
                <xsl:with-param name="pathText">
                    <xsl:value-of select="name()"/>    <xsl:text>/</xsl:text><xsl:value-of select="$pathText"/>
                </xsl:with-param>   
            </xsl:apply-templates>
        </xsl:when>
        <xsl:otherwise>
            <xsl:message><xsl:value-of select="name()"/> has no parent!</xsl:message>
            <xsl:value-of select="$pathText"/>
        </xsl:otherwise>
    </xsl:choose>   
</xsl:template>
</xsl:stylesheet>

元素名称:路径:
获取xpath函数路径文本的顶部:
他有父母
/
没有父母!
另一种方法是使用xsl:apply templates,但使用mode参数将其与其他模板匹配分开。试试这个XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml"/>
<xsl:template match="/">
    <result>
        <xsl:apply-templates/>
    </result>
</xsl:template>

<xsl:template match="*">
    <xsl:variable name="xpath">
        <xsl:call-template name="getXpath">
            <xsl:with-param name="pathText" select="''"/>
        </xsl:call-template>
    </xsl:variable>

    <element>element name : <xsl:value-of select="name()"/> path : <xsl:value-of select="$xpath"/></element>
    <xsl:apply-templates/>
</xsl:template>

<xsl:template name="getXpath">
<xsl:param name="pathText"/>
<xsl:param name="node" select="." />

<xsl:message>top of get xpath func path text : <xsl:value-of select="$pathText"/>    </xsl:message>
    <xsl:choose>
        <xsl:when test="$node/ancestor::*">
            <xsl:message><xsl:value-of select="name($node)"/> has a parent</xsl:message>
            <xsl:call-template name="getXpath">
                <xsl:with-param name="pathText">
                    <xsl:value-of select="name($node)"/>    <xsl:text>/</xsl:text><xsl:value-of select="$pathText"/>
                </xsl:with-param>   
                <xsl:with-param name="node" select="$node/parent::*" />
            </xsl:call-template>
        </xsl:when>
        <xsl:otherwise>
            <xsl:message><xsl:value-of select="name($node)"/> has no parent!</xsl:message>
            <xsl:value-of select="$pathText"/>
        </xsl:otherwise>
    </xsl:choose>   
</xsl:template>
</xsl:stylesheet>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml"/>
<xsl:template match="/">
    <result>
        <xsl:apply-templates/>
    </result>
</xsl:template>

<xsl:template match="*">
    <xsl:variable name="xpath">
        <xsl:apply-templates select="." mode="getXpath">
            <xsl:with-param name="pathText" select="''"/>
        </xsl:apply-templates>
    </xsl:variable>

    <element>element name : <xsl:value-of select="name()"/> path : <xsl:value-of select="$xpath"/></element>
    <xsl:apply-templates/>
</xsl:template>

<xsl:template match="*" mode="getXpath">
<xsl:param name="pathText"/>
<xsl:message>top of get xpath func path text : <xsl:value-of select="$pathText"/>    </xsl:message>
    <xsl:choose>
        <xsl:when test="ancestor::*">
            <xsl:message><xsl:value-of select="name()"/> has a parent</xsl:message>
            <xsl:apply-templates select=".." mode="getXpath">
                <xsl:with-param name="pathText">
                    <xsl:value-of select="name()"/>    <xsl:text>/</xsl:text><xsl:value-of select="$pathText"/>
                </xsl:with-param>   
            </xsl:apply-templates>
        </xsl:when>
        <xsl:otherwise>
            <xsl:message><xsl:value-of select="name()"/> has no parent!</xsl:message>
            <xsl:value-of select="$pathText"/>
        </xsl:otherwise>
    </xsl:choose>   
</xsl:template>
</xsl:stylesheet>

元素名称:路径:
获取xpath函数路径文本的顶部:
他有父母
/
没有父母!

您确实可以将节点作为参数传递给模板

<xsl:template name="getXpath">
<xsl:param name="pathText"/>
<xsl:param name="node" select="." />

要对其应用轴,例如测试祖先,您可以执行以下操作

<xsl:when test="$node/ancestor::*">

要在递归调用模板时将其父元素传递给模板,请执行以下操作:

<xsl:with-param name="node" select="$node/parent::*" />

试试这个XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml"/>
<xsl:template match="/">
    <result>
        <xsl:apply-templates/>
    </result>
</xsl:template>

<xsl:template match="*">
    <xsl:variable name="xpath">
        <xsl:call-template name="getXpath">
            <xsl:with-param name="pathText" select="''"/>
        </xsl:call-template>
    </xsl:variable>

    <element>element name : <xsl:value-of select="name()"/> path : <xsl:value-of select="$xpath"/></element>
    <xsl:apply-templates/>
</xsl:template>

<xsl:template name="getXpath">
<xsl:param name="pathText"/>
<xsl:param name="node" select="." />

<xsl:message>top of get xpath func path text : <xsl:value-of select="$pathText"/>    </xsl:message>
    <xsl:choose>
        <xsl:when test="$node/ancestor::*">
            <xsl:message><xsl:value-of select="name($node)"/> has a parent</xsl:message>
            <xsl:call-template name="getXpath">
                <xsl:with-param name="pathText">
                    <xsl:value-of select="name($node)"/>    <xsl:text>/</xsl:text><xsl:value-of select="$pathText"/>
                </xsl:with-param>   
                <xsl:with-param name="node" select="$node/parent::*" />
            </xsl:call-template>
        </xsl:when>
        <xsl:otherwise>
            <xsl:message><xsl:value-of select="name($node)"/> has no parent!</xsl:message>
            <xsl:value-of select="$pathText"/>
        </xsl:otherwise>
    </xsl:choose>   
</xsl:template>
</xsl:stylesheet>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml"/>
<xsl:template match="/">
    <result>
        <xsl:apply-templates/>
    </result>
</xsl:template>

<xsl:template match="*">
    <xsl:variable name="xpath">
        <xsl:apply-templates select="." mode="getXpath">
            <xsl:with-param name="pathText" select="''"/>
        </xsl:apply-templates>
    </xsl:variable>

    <element>element name : <xsl:value-of select="name()"/> path : <xsl:value-of select="$xpath"/></element>
    <xsl:apply-templates/>
</xsl:template>

<xsl:template match="*" mode="getXpath">
<xsl:param name="pathText"/>
<xsl:message>top of get xpath func path text : <xsl:value-of select="$pathText"/>    </xsl:message>
    <xsl:choose>
        <xsl:when test="ancestor::*">
            <xsl:message><xsl:value-of select="name()"/> has a parent</xsl:message>
            <xsl:apply-templates select=".." mode="getXpath">
                <xsl:with-param name="pathText">
                    <xsl:value-of select="name()"/>    <xsl:text>/</xsl:text><xsl:value-of select="$pathText"/>
                </xsl:with-param>   
            </xsl:apply-templates>
        </xsl:when>
        <xsl:otherwise>
            <xsl:message><xsl:value-of select="name()"/> has no parent!</xsl:message>
            <xsl:value-of select="$pathText"/>
        </xsl:otherwise>
    </xsl:choose>   
</xsl:template>
</xsl:stylesheet>

元素名称:路径:
获取xpath函数路径文本的顶部:
他有父母
/
没有父母!
另一种方法是使用xsl:apply templates,但使用mode参数将其与其他模板匹配分开。试试这个XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml"/>
<xsl:template match="/">
    <result>
        <xsl:apply-templates/>
    </result>
</xsl:template>

<xsl:template match="*">
    <xsl:variable name="xpath">
        <xsl:call-template name="getXpath">
            <xsl:with-param name="pathText" select="''"/>
        </xsl:call-template>
    </xsl:variable>

    <element>element name : <xsl:value-of select="name()"/> path : <xsl:value-of select="$xpath"/></element>
    <xsl:apply-templates/>
</xsl:template>

<xsl:template name="getXpath">
<xsl:param name="pathText"/>
<xsl:param name="node" select="." />

<xsl:message>top of get xpath func path text : <xsl:value-of select="$pathText"/>    </xsl:message>
    <xsl:choose>
        <xsl:when test="$node/ancestor::*">
            <xsl:message><xsl:value-of select="name($node)"/> has a parent</xsl:message>
            <xsl:call-template name="getXpath">
                <xsl:with-param name="pathText">
                    <xsl:value-of select="name($node)"/>    <xsl:text>/</xsl:text><xsl:value-of select="$pathText"/>
                </xsl:with-param>   
                <xsl:with-param name="node" select="$node/parent::*" />
            </xsl:call-template>
        </xsl:when>
        <xsl:otherwise>
            <xsl:message><xsl:value-of select="name($node)"/> has no parent!</xsl:message>
            <xsl:value-of select="$pathText"/>
        </xsl:otherwise>
    </xsl:choose>   
</xsl:template>
</xsl:stylesheet>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml"/>
<xsl:template match="/">
    <result>
        <xsl:apply-templates/>
    </result>
</xsl:template>

<xsl:template match="*">
    <xsl:variable name="xpath">
        <xsl:apply-templates select="." mode="getXpath">
            <xsl:with-param name="pathText" select="''"/>
        </xsl:apply-templates>
    </xsl:variable>

    <element>element name : <xsl:value-of select="name()"/> path : <xsl:value-of select="$xpath"/></element>
    <xsl:apply-templates/>
</xsl:template>

<xsl:template match="*" mode="getXpath">
<xsl:param name="pathText"/>
<xsl:message>top of get xpath func path text : <xsl:value-of select="$pathText"/>    </xsl:message>
    <xsl:choose>
        <xsl:when test="ancestor::*">
            <xsl:message><xsl:value-of select="name()"/> has a parent</xsl:message>
            <xsl:apply-templates select=".." mode="getXpath">
                <xsl:with-param name="pathText">
                    <xsl:value-of select="name()"/>    <xsl:text>/</xsl:text><xsl:value-of select="$pathText"/>
                </xsl:with-param>   
            </xsl:apply-templates>
        </xsl:when>
        <xsl:otherwise>
            <xsl:message><xsl:value-of select="name()"/> has no parent!</xsl:message>
            <xsl:value-of select="$pathText"/>
        </xsl:otherwise>
    </xsl:choose>   
</xsl:template>
</xsl:stylesheet>

元素名称:路径:
获取xpath函数路径文本的顶部:
他有父母
/
没有父母!

如果只对每个执行
xsl:for-each,则不必将节点作为参数传递

下面是XSLT的一个修改示例。(请注意,位置谓词仅在需要时在路径中输出。)


元素名称:路径:
输出(使用问题的输入)


元素名称:testfile路径:/testfile
元素名称:节路径:/testfile/section
元素名称:标题路径:/testfile/section/title
元素名称:para路径:/testfile/section/para

如果只对每个
执行
xsl:for-each,则不必将节点作为参数传递

下面是XSLT的一个修改示例。(请注意,位置谓词仅在需要时在路径中输出。)


元素名称:路径:
输出(使用问题的输入)


元素名称:testfile路径:/testfile
元素名称:节路径:/testfile/section
元素名称:标题路径:/testfile/section/title
元素名称:para路径:/testfile/section/para

出于自身的价值,我在大约十年前编写了一个简单的XPath生成模板,该模板位于:

清单4。在XSLT中生成伪XPath的模板
/
/正文()[
]
/评论()[
]
/处理指令()[
]
/
[
]
/命名空间::
/@
这是一个XSLT1.0解决方案,结构清晰。简化它可能是可能的,尤其是在使用XSLT和XPath2.0的情况下

正如我在那里解释的那样,这个“伪XPath”版本忽略了名称空间问题,因为我不需要它作为概念验证工具,而且它是用于人类可读的消息而不是用于执行。通过将名称空间更改为写出指定节点类型的路径,并使用显式测试localname和名称空间URI的谓词,可以正确地管理名称空间。由此产生的路径将更为庞大,人类更难处理。如果你愿意的话,为读者做运动

你也可能是