使用xslt生成xpath

时间:2014-08-01 18:05:32

标签: xml xslt xpath

我正在尝试为xml文档中的元素生成xpath。我发现这个解决方案Generate/get xpath from XML node java非常接近我所需要的,除了我希望它在一个路径中列出所有元素属性而不是重新生成相同的路径。例如

/root/elemA[2][@attribute1='first'][@attribute2='second']

而不是

/root/elemA[2][@attribute1='first']
/root/elemA[2][@attribute2='second']

我对xslt很新,并且一直在使用这个模板,但我似乎无法弄清楚如何更改输出。

1 个答案:

答案 0 :(得分:3)

试试这个......

<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="text()"/>

    <xsl:template match="*">
        <xsl:for-each select="ancestor-or-self::*">
            <xsl:value-of select="concat('/',local-name())"/>
            <!--Predicate is only output when needed.-->
            <xsl:if test="(preceding-sibling::*|following-sibling::*)[local-name()=local-name(current())]">
                <xsl:value-of select="concat('[',count(preceding-sibling::*[local-name()=local-name(current())])+1,']')"/>
            </xsl:if>
            <!--Output attributes.-->
            <xsl:if test="@*">
                <xsl:text>[</xsl:text>
                <xsl:apply-templates select="@*"/>
                <xsl:text>]</xsl:text>
            </xsl:if>
        </xsl:for-each>
        <xsl:text>&#xA;</xsl:text>
        <xsl:apply-templates select="node()"/>
    </xsl:template>

    <xsl:template match="@*">
        <xsl:if test="position() != 1">
            <xsl:text>][</xsl:text>
        </xsl:if>
        <xsl:value-of select="concat('@',local-name(),'=&quot;',.,'&quot;')"/>
    </xsl:template>

</xsl:stylesheet>

使用链接问题的输入:

<root>
    <elemA>one</elemA>
    <elemA attribute1='first' attribute2='second'>two</elemA>
    <elemB>three</elemB>
    <elemA>four</elemA>
    <elemC>
        <elemB>five</elemB>
    </elemC>
</root>

产生以下输出:

/root
/root/elemA[1]
/root/elemA[2][@attribute1="first"][@attribute2="second"]
/root/elemB
/root/elemA[3]
/root/elemC
/root/elemC/elemB

修改

这是一个基于评论的更新的XSLT 无论如何它只是输出属性,如果它是孩子?例如/body/text[@attr='1']然后/body/text/h1[@attr='1']

<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="text()"/>

    <xsl:template match="*">
        <xsl:variable name="id" select="generate-id()"/>
        <xsl:for-each select="ancestor-or-self::*">
            <xsl:value-of select="concat('/',local-name())"/>
            <!--Predicate is only output when needed.-->
            <xsl:if test="(preceding-sibling::*|following-sibling::*)[local-name()=local-name(current())]">
                <xsl:value-of select="concat('[',count(preceding-sibling::*[local-name()=local-name(current())])+1,']')"/>
            </xsl:if>
            <!--Output attributes.-->
            <xsl:if test="@* and generate-id() = $id">
                <xsl:text>[</xsl:text>
                <xsl:apply-templates select="@*"/>
                <xsl:text>]</xsl:text>
            </xsl:if>
        </xsl:for-each>
        <xsl:text>&#xA;</xsl:text>
        <xsl:apply-templates select="node()"/>
    </xsl:template>

    <xsl:template match="@*">
        <xsl:if test="position() != 1">
            <xsl:text>][</xsl:text>
        </xsl:if>
        <xsl:value-of select="concat('@',local-name(),'=&quot;',.,'&quot;')"/>
    </xsl:template>

</xsl:stylesheet>