如何使用XSLT获取不同元素名称及其属性名称的列表

时间:2014-11-26 10:43:50

标签: xml xslt

我想使用xslt“扫描”我的xml文件,并获取不同元素名称列表以及其属性名称。

我的XML:

<?xml version="1.0" encoding="UTF-8"?>
<dictionary>
    <entry>
        <form type="hyperlemma" xml:lang="cu">
            <note type="editor's comment">CHECK</note>
            <orth>hlE1</orth>
        </form>
        <form type="lemma" xml:lang="cu">
            <orth>lE1</orth>
        </form>
        <form type="variant" xml:lang="cu">
            <orth>var5</orth>
        </form>
    </entry>
    <entry>
        <form type="hyperlemma" xml:lang="cu">
            <orth>hlE2</orth>
        </form>
        <form type="lemma" xml:lang="cu">
            <orth>lE2</orth>
        </form>
    </entry>
</dictionary>

How to list complete XML document using XSLT中记录了获取不同元素名称列表的方法(请参阅Dimitre Novatchev的回答)。

使用此样式表

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="xs"
    version="2.0">
    <xsl:output method="text"/>
    <xsl:strip-space elements="*" />

    <xsl:key name="kElemByName" match="*" use="name(.)"/>

    <xsl:template match="
        *[generate-id()
        =
        generate-id(key('kElemByName', name(.))[1])
        ]">
        <xsl:value-of select="concat(name(.), '&#xA;')"/>
        <xsl:apply-templates select="*"/>
    </xsl:template>

    <xsl:template match="text()"/>

</xsl:stylesheet>

(正确)输出

dictionary
entry
form
note
orth

是否也可以获取属性名称?我想有以下输出

dictionary
entry
form type="hyperlemma" xml:lang="cu"
form type="lemma" xml:lang="cu"
form type="variant" xml:lang="cu"
note type="editor's comment"
orth

我如何实现这一目标?

2 个答案:

答案 0 :(得分:1)

当您使用XSLT 2.0时,我只需使用for-each-group解析它,并根据名称和属性计算分组键:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="xs"
    version="2.0">
    <xsl:output method="text"/>
    <xsl:strip-space elements="*" />

    <xsl:template match="/">
      <xsl:for-each-group select="//*" group-by="string-join((name(), @*/concat(name(), '=&quot;', ., '&quot;')), ' ')">
        <xsl:value-of select="concat(current-grouping-key(), '&#10;')"/>
      </xsl:for-each-group>
    </xsl:template>

</xsl:stylesheet>

输出

dictionary
entry
form type="hyperlemma" xml:lang="cu"
note type="editor's comment"
orth
form type="lemma" xml:lang="cu"
form type="variant" xml:lang="cu"
撒克逊9.5对我来说。

如果要对输出进行排序,可以使用

  <xsl:template match="/">
      <xsl:for-each-group select="//*" group-by="string-join((name(), @*/concat(name(), '=&quot;', ., '&quot;')), ' ')">
        <xsl:sort select="current-grouping-key()"/>
        <xsl:value-of select="concat(current-grouping-key(), '&#10;')"/>
      </xsl:for-each-group>
    </xsl:template>

我得到的方式

dictionary
entry
form type="hyperlemma" xml:lang="cu"
form type="lemma" xml:lang="cu"
form type="variant" xml:lang="cu"
note type="editor's comment"
orth

我认为要获得一致的结果,代码首先还需要按名称对属性进行排序,因为我怀疑输入是否为<foo att1="value1" att2="value2"/><foo att2="value2" att1="value1"/>,您只需要一个元素输出

可以使用

执行排序
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:mf="http://example.com/mf"
    exclude-result-prefixes="xs mf"
    version="2.0">
    <xsl:output method="text"/>
    <xsl:strip-space elements="*" />

    <xsl:function name="mf:sort" as="attribute()*">
      <xsl:param name="attributes" as="attribute()*"/>
      <xsl:perform-sort select="$attributes">
        <xsl:sort select="name()"/>
      </xsl:perform-sort>
    </xsl:function>

    <xsl:template match="/">
      <xsl:for-each-group select="//*" group-by="string-join((name(), mf:sort(@*)/concat(name(), '=&quot;', ., '&quot;')), ' ')">
        <xsl:sort select="current-grouping-key()"/>
        <xsl:value-of select="concat(current-grouping-key(), '&#10;')"/>
      </xsl:for-each-group>
    </xsl:template>

</xsl:stylesheet>

答案 1 :(得分:1)

更简单的是使用distinct-values()

<xsl:template match="/">
   <xsl:value-of select="distinct-values(//*/string-join(
                         (name(), @*/concat(name(), '=&quot;', ., '&quot;')), ' '))" 
           separator="&#10;"/>
</xsl:template>