【问题标题】:Output Context Node (full path) in XSLT 1.0?XSLT 1.0 中的输出上下文节点(完整路径)?
【发布时间】:2015-06-12 17:17:47
【问题描述】:

出于调试目的,从模板中输出上下文节点的完整路径会很方便,是否有未缩写的 xpath 或函数来报告这一点?

示例模板:

<xsl:template match="@first">
        <tr>
            <td>
                <xsl:value-of select="??WHAT TO PUT IN HERE??"/>
            </td>
        </tr>
</xsl:template>

示例(删节)输入文档:

<people>
<person>
<name first="alan">
...

模板的输出类似于:

people / person / name / @first 

或类似的东西。

【问题讨论】:

标签: debugging xslt contextpath


【解决方案1】:

此转换为所需节点生成 XPath 表达式

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output method="text"/>
 <xsl:strip-space elements="*"/>

    <xsl:template match="/">
        <xsl:variable name="vNode" select=
        "/*/*[2]/*/@first"/>
        <xsl:apply-templates select="$vNode" mode="path"/>
    </xsl:template>

    <xsl:template match="*" mode="path">
        <xsl:value-of select="concat('/',name())"/>
        <xsl:variable name="vnumPrecSiblings" select=
        "count(preceding-sibling::*[name()=name(current())])"/>
        <xsl:variable name="vnumFollSiblings" select=
        "count(following-sibling::*[name()=name(current())])"/>
        <xsl:if test="$vnumPrecSiblings or $vnumFollSiblings">
            <xsl:value-of select=
            "concat('[', $vnumPrecSiblings +1, ']')"/>
        </xsl:if>
    </xsl:template>

    <xsl:template match="@*" mode="path">
     <xsl:apply-templates select="ancestor::*" mode="path"/>
     <xsl:value-of select="concat('/@', name())"/>
    </xsl:template>
</xsl:stylesheet>

应用于以下 XML 文档时

<people>
 <person>
  <name first="betty" last="jones"/>
 </person>
 <person>
  <name first="alan" last="smith"/>
 </person>
</people>

产生想要的正确结果

/people/person[2]/name/@first

【讨论】:

  • 这确实适用于给出的示例 XML,谢谢。我现在正试图让它与我更复杂的真实示例一起使用,但它似乎不匹配......我需要仔细研究并找出原因......edit我明白了它,那里有一个硬编码的 @first 引用...让我更改这一轮以适合我的实际 XML...
  • 是的,效果很好 - 非常感谢。对于我的实际需要,我需要对其进行一些编辑以更普遍地工作,但这是一个很棒的模板。干杯!
  • 顺便说一句(我认为其他人也在 stackoverflow 上的其他地方问过这个问题) - 是否有一个通用的 'xsl:pwd' 或 'xsl:name-of' 可用,可以更普遍地注入到任何用于调试的文档我都想知道......我可以想象(也许)这些东西的递归性质意味着模板不“知道”文档中的总深度(无需向上遍历)所以我猜这就是为什么我们没有现成的......
  • @monojohnny:不,没有一个特殊的函数可以返回一个节点的 XPath 表达式——可能至少部分是因为存在多个这样的 XPath 表达式并且存在没有“正常形式”的定义。
【解决方案2】:

这是一个样式表(值可疑),它打印文档中每个元素和属性的路径:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="text" />
    <xsl:strip-space elements="*" />
    <xsl:template match="*">
        <xsl:param name="pathToHere" select="''" />
        <xsl:variable name="precSiblings"
            select="count(preceding-sibling::*[name()=name(current())])" />
        <xsl:variable name="follSiblings"
            select="count(following-sibling::*[name()=name(current())])" />
        <xsl:variable name="fullPath"
            select="concat($pathToHere, '/', name(),
                substring(concat('[', $precSiblings + 1, ']'), 
                    1 div ($follSiblings or $precSiblings)))" />
        <xsl:value-of select="concat($fullPath, '&#xA;')" />
        <xsl:apply-templates select="@*|*">
            <xsl:with-param name="pathToHere" select="$fullPath" />
        </xsl:apply-templates>
    </xsl:template>
    <xsl:template match="@*">
        <xsl:param name="pathToHere" select="''" />
        <xsl:value-of select="concat($pathToHere, '/@', name(),  '&#xA;')" />
    </xsl:template>
</xsl:stylesheet>

应用于此输入时:

<people>
    <person>
        <name first="betty" last="jones" />
    </person>
    <person>
        <name first="alan" last="smith" />
    </person>
    <singleElement />
</people>

生产:

/people
/people/person[1]
/people/person[1]/name
/people/person[1]/name/@first
/people/person[1]/name/@last
/people/person[2]
/people/person[2]/name
/people/person[2]/name/@first
/people/person[2]/name/@last
/people/singleElement

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-04-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-03
    • 2018-05-13
    • 2010-11-04
    相关资源
    最近更新 更多