首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >提取所有节点的Xpath,然后提取它们的属性

提取所有节点的Xpath,然后提取它们的属性
EN

Stack Overflow用户
提问于 2013-01-11 16:32:41
回答 1查看 742关注 0票数 2

在过去的两天里,我一直在努力使用xslt,因为我的初学者status.My要求是,给定任何输入XML文件,我希望输出是所有标记在原始XML文档中出现的顺序的所有标记的列表( XPaths,然后是parent,parents属性列表/子,父/子/子,以此类推)。XSLT不应该特定于任何一个XMl模式。它应该适用于任何有效的XML文件。

例如:

如果输入XML为:

代码语言:javascript
复制
<v1:Root>
<v1:UserID>test</v1:UserID>
<v1:Destination>test</v1:Destination>
<v1:entity name="entiTyName">
<v11:attribute name="entiTyName"/>
<v11:attribute name="entiTyName"/>
<v11:attribute name="entiTyName"/>
<v11:filter type="entiTyName">
<v11:condition attribute="entiTyName" operator="eq" value="{FB8D669E-D090-E011-8F43-0050568E222C}"/>
<v11:condition attribute="entiTyName" operator="eq" value="1"/>
</v11:filter>
<v11:filter type="or">
<v11:filter type="or">
<v11:filter type="and">
<v11:filter type="and">
<v11:condition attribute="cir_customerissuecode" operator="not-like" value="03%"/>
</v11:filter>
</v11:filter>
</v11:filter>
</v11:filter>
</v1:entity>
</v1:Root>

我希望我的输出是:

代码语言:javascript
复制
/v1:Root/v1:UserID
/v1:Root/v1:Destination
/v1:Root/v1:entity/@name
/v1:Root/v1:entity/v11:attribute
/v1:Root/v1:entity/v11:attribute/@name
/v1:Root/v1:entity/v11:attribute[2]
/v1:Root/v1:entity/v11:attribute[2]/@name
/v1:Root/v1:entity/v11:attribute[3]
/v1:Root/v1:entity/v11:attribute[3]/@name
/v1:Root/v1:entity/v11:filter/@type
/v1:Root/v1:entity/v11:filter/v11:condition
/v1:Root/v1:entity/v11:filter/v11:condition/@attribute
/v1:Root/v1:entity/v11:filter/v11:condition/@operator
/v1:Root/v1:entity/v11:filter/v11:condition/@value
/v1:Root/v1:entity/v11:filter/v11:condition[2]
/v1:Root/v1:entity/v11:filter/v11:condition[2]/@attribute
/v1:Root/v1:entity/v11:filter/v11:condition[2]/@operator
/v1:Root/v1:entity/v11:filter/v11:condition[2]/@value
/v1:Root/v1:entity/v11:filter[2]/v11:filter/@type
/v1:Root/v1:entity/v11:filter[2]/v11:filter/v11:filter/@type
/v1:Root/v1:entity/v11:filter[2]/v11:filter/v11:filter/v11:filter/@type
/v1:Root/v1:entity/v11:filter[2]/v11:filter/v11:filter/v11:filter/v11:condition
/v1:Root/v1:entity/v11:filter[2]/v11:filter/v11:filter/v11:filter/v11:condition/@attribute
/v1:Root/v1:entity/v11:filter[2]/v11:filter/v11:filter/v11:filter/v11:condition/@operator
/v1:Root/v1:entity/v11:filter[2]/v11:filter/v11:filter/v11:filter/v11:condition/@value
/v1:Root/v1:entity/v11:filter[2]/v11:filter/v11:filter/v11:filter[2]/@type
/v1:Root/v1:entity/v11:filter[2]/v11:filter/v11:filter/v11:filter[2]/v11:condition
/v1:Root/v1:entity/v11:filter[2]/v11:filter/v11:filter/v11:filter[2]/v11:condition/@attribute
/v1:Root/v1:entity/v11:filter[2]/v11:filter/v11:filter/v11:filter[2]/v11:condition/@operator
/v1:Root/v1:entity/v11:filter[2]/v11:filter/v11:filter/v11:filter[2]/v11:condition/@value
/v1:Root/v1:entity/v11:filter[2]/v11:filter/v11:filter/v11:filter[2]/v11:condition[2]
/v1:Root/v1:entity/v11:filter[2]/v11:filter/v11:filter/v11:filter[2]/v11:condition[2]/@attribute
/v1:Root/v1:entity/v11:filter[2]/v11:filter/v11:filter/v11:filter[2]/v11:condition[2]/@operator
/v1:Root/v1:entity/v11:filter[2]/v11:filter/v11:filter/v11:filter[2]/v11:condition[2]/@value

因此,它基本上是每个元素的所有XPath,然后是元素属性的Xpath。

我随身带着一个XSLT,它是这样的:

代码语言:javascript
复制
    <xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="text" indent="no" />
    <xsl:template match="*[not(child::*)]">
        <xsl:for-each select="ancestor-or-self::*">
            <xsl:value-of select="concat('/', name())" />
            <xsl:if test="count(preceding-sibling::*[name() = name(current())]) != 0">
                <xsl:value-of
                    select="concat('[', count(preceding-sibling::*[name() = name(current())]) + 1, ']')" />
            </xsl:if>
        </xsl:for-each>

        <xsl:apply-templates select="*" />
    </xsl:template>

    <xsl:template match="/">
        <xsl:apply-templates select="*" />
    </xsl:template>

</xsl:stylesheet>

生成的THe输出不会迎合复杂的标签,也不会迎合生成的Xpath列表中的标签属性:(.

请帮助我修复这个xslt,以生成上面提到的输出。

以上THe的输出如下所示:

代码语言:javascript
复制
/v1:Root/v1:UserID
/v1:Root/v1:Destination
/v1:Root/v1:entity/v11:attribute
/v1:Root/v1:entity/v11:attribute[2]
/v1:Root/v1:entity/v11:attribute[3]
/v1:Root/v1:entity/v11:filter/v11:condition
/v1:Root/v1:entity/v11:filter/v11:condition[2]
/v1:Root/v1:entity/v11:filter[2]/v11:filter/v11:filter/v11:filter/v11:condition
/v1:Root/v1:entity/v11:filter[2]/v11:filter/v11:filter/v11:filter[2]/v11:condition
/v1:Root/v1:entity/v11:filter[2]/v11:filter/v11:filter/v11:filter[2]/v11:condition[2]
/v1:Root/v1:entity/v11:filter[2]/v11:filter[2]/v11:filter/v11:condition
/v1:Root/v1:entity/v11:filter[2]/v11:filter[2]/v11:filter[2]/v11:condition
/v1:Root/v1:entity/v11:filter[2]/v11:filter[2]/v11:filter[2]/v11:condition[2]
/v1:Root/v1:entity/v11:filter[2]/v11:filter[2]/v11:filter[2]/v11:condition[3]
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-01-11 16:59:55

我认为您的示例输入和输出之间存在差异,因为输出描述了一个带有两个conditionfilter元素,而这两个元素不在源XML中。无论如何,我相信这是可行的:

代码语言:javascript
复制
<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="text" indent="no" />
  <!-- Handle attributes -->
  <xsl:template match="@*">
    <xsl:apply-templates select="ancestor-or-self::*" mode="buildPath" />
    <xsl:value-of select="concat('/@', name())"/>
    <xsl:text>&#xA;</xsl:text>
  </xsl:template>

  <!-- Handle non-leaf elements (just pass processing downwards) -->
  <xsl:template match="*[@* and *]">
    <xsl:apply-templates select="@* | *" />
  </xsl:template>

  <!-- Handle leaf elements -->
  <xsl:template match="*[not(*)]">
    <xsl:apply-templates select="ancestor-or-self::*" mode="buildPath" />
    <xsl:text>&#xA;</xsl:text>
    <xsl:apply-templates select="@*" />
  </xsl:template>

  <!-- Outputs a path segment for the matched element: '/' + name() + [ordinalPredicate > 1] -->
  <xsl:template match="*" mode="buildPath">
    <xsl:value-of select="concat('/', name())" />
    <xsl:variable name="sameNameSiblings" select="preceding-sibling::*[name() = name(current())]" />
    <xsl:if test="$sameNameSiblings">
      <xsl:value-of select="concat('[', count($sameNameSiblings) + 1, ']')" />
    </xsl:if>
  </xsl:template>

  <!-- Ignore text -->
  <xsl:template match="text()" />
</xsl:stylesheet>
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/14274317

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档