0

我有一个要求,我必须从不同的层次结构中提取和列出 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:原理很简单:我遇到根元素“\”写入文本和 for-each 层次结构我提供绝对 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>

有没有更好的办法??

4

2 回答 2

2

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

  • 节点没有按名称分组,例如,C 元素可能位于 A 元素的根而不是 B 元素的子元素。
  • 当您在层次结构中的任何位置添加与 A、B、C 不同的节点时(但是,它们必须是 Wrapper 的子节点),它们的 @Id 将由 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>
于 2013-02-21T09:30:42.477 回答
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>
于 2013-02-21T09:08:11.770 回答