如何构建分层部分/子部分/段落“路径”

时间:2013-03-15 11:47:00

标签: xml xslt

我知道这与原始问题有所不同,但这是一个我想要实现以下预期结果的思考过程:

XML INPUT:

<section hangIndent="no" indent="arabic 1 digit"
isProposedAmendment="no" label="2A">
<title>AAA</title>
<body>
 BBB<subSection label="1">
  <body>
    <para hangIndent="yes" indent="loweralpha 1 character"
     isProposedAmendment="no" label="a">
      <body>
        CCC
      </body>
    </para>
    <para hangIndent="yes" indent="loweralpha 1 character"
      isProposedAmendment="no" label="b">
      <body>
        DDD
      </body>
    </para>
    <para hangIndent="yes" indent="loweralpha 1 character"
     isProposedAmendment="no" label="c">
      <body>
        EEE
      </body>
    </para>
  </body>
</subSection>
</body>
<annotation isProposedAmendment="no">
FFFFF
</annotation>
</section>

所需的输出:我根据每个节点的标签构建一个xmlpath名称,并将其插入每个端点。

<nm:xmlpath name ="2A" />
<section hangIndent="no" indent="arabic 1 digit"
isProposedAmendment="no" label="2A">
<title>AAA</title>
<body>
 BBB
<nm:xmlpath name ="2A 1" /> 
<subSection label="1">
  <body>
    <nm:xmlpath name ="2A 1(a)" />
    <para hangIndent="yes" indent="loweralpha 1 character"
isProposedAmendment="no" label="a">
      <body>
        CCC
      </body>
    </para>
    <nm:xmlpath name ="2A 1(b)" />
    <para hangIndent="yes" indent="loweralpha 1 character"
  isProposedAmendment="no" label="b">
      <body>
        DDD
      </body>
    </para>
    <nm:xmlpath name ="2A 1(c)" />
    <para hangIndent="yes" indent="loweralpha 1 character"
  isProposedAmendment="no" label="c">
      <body>
        EEE
      </body>
    </para>
  </body>
</subSection>
</body>
<annotation isProposedAmendment="no">
FFFFF
</annotation>
</section>

2 个答案:

答案 0 :(得分:0)

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

<xsl:template match="*">
  <xsl:copy>
    <xsl:value-of select="text()[1]"/>
  </xsl:copy>
</xsl:template>

应该足够了。

答案 1 :(得分:0)

基本方法是使模板匹配具有label属性的任何元素,并在该元素之前插入从您找到的所有nm:xmlpath属性构造的label父母,祖父母等等。

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

  <xsl:template match="@*|node()" name="identity">
    <xsl:copy><xsl:apply-templates select="@*|node()" /></xsl:copy>
  </xsl:template>

  <xsl:template match="*[@label]">
    <nm:xmlpath>
      <xsl:attribute name="name">
        <xsl:apply-templates select="." mode="xmlpath" />
      </xsl:attribute>
    </nm:xmlpath>
    <xsl:call-template name="identity" />
  </xsl:template>

  <!-- templates to construct the xmlpath, these should produce text nodes -->

  <!-- general case - path is the enclosing path (if any), followed by space,
       followed by our own @label -->
  <xsl:template match="*" mode="xmlpath">
    <xsl:if test="ancestor::*[@label]">
      <xsl:apply-templates select="ancestor::*[@label][1]" mode="xmlpath" />
      <xsl:text> </xsl:text>
    </xsl:if>
    <xsl:value-of select="@label" />
  </xsl:template>

  <!-- special case for para - no space after enclosing path, and surround
       our label with () -->
  <xsl:template match="para" mode="xmlpath">
    <xsl:apply-templates select="ancestor::*[@label][1]" mode="xmlpath" />
    <xsl:value-of select="concat('(', @label, ')')" />
  </xsl:template>

</xsl:stylesheet>

为了生成格式良好的XML,输入文档的根元素必须具有label属性 - 如果确实如此,我们将尝试插入{在它之前{1}},为输出文档提供两个根级元素。