【问题标题】:How to traverse a nested XML structure using templates如何使用模板遍历嵌套的 XML 结构
【发布时间】:2011-09-06 02:04:47
【问题描述】:

我是 XSL 的新手,正在从头开始解决问题。

我有一个包含以下结构的源 XML 文件:-

<root>
  <Header>

  </Header>

  <DetailRecord>
    <CustomerNumber>1</CustomerNumber>
    <DetailSubRecord>
      <Address>London</Address>
    </DetailSubRecord>
    <DetailSubRecord>
      <Address>Hull</Address>
    </DetailSubRecord>

  </DetailRecord>

  <DetailRecord>
    <CustomerNumber>2</CustomerNumber>
    <DetailSubRecord>
      <Address>Birmingham</Address>
    </DetailSubRecord>
    <DetailSubRecord>
      <Address>Manchester</Address>
    </DetailSubRecord>

  </DetailRecord>
  <Footer>

  </Footer>

</root>

其中有多个&lt;DetailRecord&gt;s,每个&lt;DetailSubRecord&gt;s 有多个。

我已经设法组合了一个 XSL,它将一组嵌套的多个 DetailRecord 输出到一个平面文件,但我无法弄清楚如何在 XSL 中引用第二个嵌套级别的地址记录。 .

到目前为止,这是我的 XSL:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:strip-space elements="*"/>
  <xsl:output method="text"/>
  <xsl:variable name="spaces" select="' '"/>
  <xsl:variable name="newline">
    <xsl:text>&#10;</xsl:text>
  </xsl:variable>
  <xsl:template match="/">
    <xsl:value-of select="root/Header/HeaderField"/>
    <xsl:copy-of select="$newline"/>
    <xsl:for-each select="root/DetailRecord">
      <xsl:value-of select="CustomerNumber"/>
      <xsl:copy-of select="$newline"/>
    </xsl:for-each>
    Trailer - recordCount - <xsl:value-of select="count(root/DetailRecord)"/>
  </xsl:template>
</xsl:stylesheet>

【问题讨论】:

  • 到目前为止,这是我的 XSL...
  • xsl:样式表>
  • 你能发布一个你的目标输出的例子吗?

标签: xml xslt nested


【解决方案1】:

这里有一个简单的示例,说明如何(从字面上)将模板应用于您的情况。因为你不太清楚所需的输出,所以我发明了一个。


XSLT 1.0Saxon 6.5.5

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

    <xsl:strip-space elements="*"/>
    <xsl:output method="text"/>

    <xsl:variable name="spaces" select="' '"/>
    <xsl:variable name="nl">
        <xsl:text>&#10;</xsl:text>
    </xsl:variable>

    <xsl:template match="/root">
        <xsl:apply-templates select="DetailRecord"/>
        <xsl:apply-templates select="Footer"/>
    </xsl:template>

    <xsl:template match="DetailRecord">
        <xsl:value-of select="concat(
            'Customer ',
            CustomerNumber, $nl)"
            />
        <xsl:apply-templates select="DetailSubRecord"/>
        <xsl:value-of select="concat(
            'Address Count:',
            count(DetailSubRecord),$nl,$nl
            )"
          />
    </xsl:template>

    <xsl:template match="DetailSubRecord">
        <xsl:value-of select="concat('-',Address,$nl)"/>
    </xsl:template>

    <xsl:template match="Footer">
        <xsl:value-of select="concat(
            'Customer Count:',
            count(preceding-sibling::DetailRecord),$nl
            )"
            />
    </xsl:template>

</xsl:stylesheet>

应用于您的输入获得:

Customer 1
-London
-Hull
Address Count:2

Customer 2
-Birmingham
-Manchester
Address Count:2

Customer Count:2

【讨论】:

    【解决方案2】:

    XSLT 是函数式语言,而不是过程式语言;大多数 XSLT 新手没有意识到 XSLT 处理器会按照它们在源代码中出现的顺序自动处理树中的每个节点。但是,如果没有模板来定义如何处理每个节点,则不会输出任何内容。

    在大多数情况下,您不需要使用&lt;xsl:for-each&gt; 来处理子元素,这已经为您完成了,您只需要定义一个模板来描述您希望如何输出每个元素。像这样:

    <xsl:template match="root">
      <xsl:apply-templates />
      <xsl:text>Trailer - recordCount - </xsl:text>
      <xsl:value-of select="count(DetailRecord)" />
    </xsl:template>
    
    <xsl:template match="HeaderField | CustomerNumber | Address">
      <xsl:value-of select="concat(.,$newline)" />
    </xsl:template>
    
    <xsl:template match="DetailSubRecord">
      <!-- do something with subrecord here -->
      <xsl:apply-templates />
    </xsl:template>
    

    第一个模板中的&lt;xsl:apply-templates /&gt; 只是告诉 XSLT 处理器处理子元素,然后它会添加记录数。

    第二个模板处理其 match 属性中包含三个名称的任何元素,并在每种情况下输出与新行连接的内容 (.)。

    当前形式的第三个模板实际上是多余的,处理器无论如何都会这样做,但您可以用更有用的东西替换该注释。

    您会注意到这并没有提供有关如何处理DetailRecord 元素的任何信息;因为您要做的就是处理它的孩子,所以您不需要指定任何内容,因为这是给定的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-12-24
      • 2023-03-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-11
      • 1970-01-01
      相关资源
      最近更新 更多