Выходной контекстный узел (полный путь) в XSLT 1.0? - PullRequest
3 голосов
/ 17 апреля 2011

Для целей отладки было бы удобно вывести полный путь узла контекста из шаблона, есть ли сокращенный 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 

или что-то похожее.

Ответы [ 2 ]

2 голосов
/ 18 апреля 2011

Это преобразование создает выражение 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
1 голос
/ 18 апреля 2011

Вот таблица стилей (сомнительного значения), которая печатает путь к каждому элементу и атрибуту в документе:

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