xslt 命名模板:如何编写一个模板来创建一个表示给定节点的 xpath 的字符串 [英] xslt named template : how to write a template that creates a string representing the xpath of a given node

查看:21
本文介绍了xslt 命名模板:如何编写一个模板来创建一个表示给定节点的 xpath 的字符串的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm trying to write a recursive named template that will show the path of a given node:

<?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>

我正在尝试这个模板:

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

<!-- stylesheet to test a named template trying to build an xpath for a given node -->
<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: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:call-template name="getXpath">
                <xsl:with-param name="pathText">
                    <xsl:value-of select="name()"/>    <xsl:text>/</xsl:text><xsl:value-of select="$pathText"/>
                    <!-- how to recursively call template with parent node? -->
                </xsl:with-param>   
            </xsl:call-template>
        </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>

根据评论,我不确定如何将上下文节点以外的节点应用于命名模板.我尝试的另一种策略是将节点作为参数发送到模板,但我不知道如何(或者是否可以)将轴应用于参数,如

As per the comment, I'm not sure how to apply a node other than the context node to the named template. The other strategy I tried was to send the node to the template as a param, but I don't know how(or if you can) apply an axis to a param, as in

$thisNode../*

等等.

我确定我遗漏了一些简单的东西......谢谢.

I'm sure it's something simple that I'm missing...thanks.

推荐答案

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

You can indeed pass in the node as a param to the template....

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

要对其应用轴,例如测试祖先,您可以这样做....

To apply an axis to it, for example to test for ancestors, you would do this....

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

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

And to pass its parent element to the template when you recursively call it, do this:

<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:apply-templates,但使用 mode 参数使其与其他模板匹配分开.试试这个 XSLT

An alternate approach is to use xsl:apply-templates, but with the mode parameter to keep it separate from other template matches. Try this 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: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>

这篇关于xslt 命名模板:如何编写一个模板来创建一个表示给定节点的 xpath 的字符串的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆