使用xslt提取和列出值集

时间:2013-02-21 08:55:43

标签: xml xslt

我有一个要求,我必须从不同的层次结构中提取和列出ID。下面是示例XML :(我提供了3级层次结构来反映肤色)

输入XML:

<Wrapper>
    <A Id="A@1">
        <B Id="B#1">
            <C Id="C$1"/>
            <C Id="C$2"/>
        </B>
        <B Id="B#2">
            <C Id="C$3"/>
            <C Id="C$4"/>
        </B>
        <B Id="B#3">
            <C Id="C$5"/>
            <C Id="C$6"/>
        </B>
        <B Id="B#4>
            <C Id="C$7"/>
            <C Id="C$8"/>
        </B>
    </A>
</Wrapper>

期望输出:

A Ids:
A@1

B Ids:
B#1
B#2
B#3
B#4

C Ids:
C$1
C$2
C$3
C$4
C$5
C$6
C$7
C$8

输入XSL:原理很简单:我遇到根元素&#34; \&#34;写下我提供的文本和每个层次结构绝对XPath 和访问ID ..这里是代码:

<?xml version ="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="text"/>
  <xsl:variable name="linefeed" select="'&#10;'"/>  

  <xsl:template match="/">

    <!--List of A Ids-->
      <xsl:text>A Ids:</xsl:text>
      <xsl:value-of select="$linefeed"/>

      <xsl:for-each select="/Wrapper/A/@Id">
        <xsl:value-of select="concat(.,$linefeed)"/>
      </xsl:for-each>

      <xsl:value-of select="$linefeed"/>


    <!--List of B Ids-->
      <xsl:text>B Ids:</xsl:text>
      <xsl:value-of select="$linefeed"/>

      <xsl:for-each select="/Wrapper/A/B/@Id">
        <xsl:value-of select="concat(.,$linefeed)"/>
      </xsl:for-each>

      <xsl:value-of select="$linefeed"/>

    <!--List of C Ids-->
      <xsl:text>C Ids:</xsl:text>
      <xsl:value-of select="$linefeed"/>

      <xsl:for-each select="/Wrapper/A/B/C/@Id">
        <xsl:value-of select="concat(.,$linefeed)"/>
      </xsl:for-each>

      <xsl:value-of select="$linefeed"/>


  </xsl:template>
 </xsl:stylesheet>

有更好的方法吗?

2 个答案:

答案 0 :(得分:2)

以下解决方案基于按名称对元素进行分组,而不是基于它们在层次结构中占据的位置。因此,即使

,此解决方案也会输出sam
  • 节点不按名称分组,例如, C元素可以是A元素的根,而不是B元素的子元素。
  • 当您在层次结构中的任何位置添加不同于A,B,C的节点时(但是,它们必须是Wrapper的子节点),它们的@Ids将由XSLT样式表自动列出。

如果您想要一个基于文档中节点位置的通用解决方案,而不是使用他们的名称对它们进行分组,那么告诉我,我会尝试调整解决方案。同时这是我在'Muenchian Grouping'中的解决方案

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:output method="text" indent="yes"/>

    <xsl:variable name="linefeed" select="'&#10;'"/>  

    <!-- Use key to group elements by local-name -->
    <xsl:key name="name-key" match="/Wrapper//*" use="local-name()"/>

    <xsl:template match="Wrapper">
        <!-- Obtain the first element for each group, where a group is
             the set of elements sharing a name -->
        <xsl:for-each select="//*[generate-id(.) = generate-id(key('name-key', local-name())[1])]">
            <!-- Print header -->
            <xsl:value-of select="concat(local-name(), ' Ids:', $linefeed)" />
            <!-- Obtain all the nodes (children of Wrapper) with the local-name of
                 the current node using the previous key -->
            <xsl:apply-templates select="key('name-key', local-name())" />
            <!-- Print line feed at the end of each different group -->
            <xsl:value-of select="$linefeed" />
        </xsl:for-each>
    </xsl:template>

    <!-- Print the information for each element -->
    <xsl:template match="*">
        <xsl:value-of select="@Id" />
        <xsl:value-of select="$linefeed" />
    </xsl:template>

</xsl:stylesheet>

答案 1 :(得分:1)

一种解决方案可能是:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="text"/>
    <xsl:variable name="linefeed" select="'&#10;'"/>

    <xsl:template match="/">
        <!--List of A Ids-->
        <xsl:text>A Ids:</xsl:text>
        <xsl:value-of select="$linefeed"/>
        <xsl:apply-templates select="//A" />

        <!--List of B Ids-->
        <xsl:text>B Ids:</xsl:text>
        <xsl:value-of select="$linefeed"/>
        <xsl:apply-templates select="//B" />

        <!--List of C Ids-->
        <xsl:text>C Ids:</xsl:text>
        <xsl:value-of select="$linefeed"/>
        <xsl:apply-templates select="//C" />
    </xsl:template>

    <xsl:template match="*">
        <xsl:value-of select="@Id" />
        <xsl:value-of select="$linefeed"/>
    </xsl:template>
</xsl:stylesheet>