如何使用模板遍历嵌套的XML结构 [英] How to traverse a nested XML structure using templates

查看:209
本文介绍了如何使用模板遍历嵌套的XML结构的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am new to XSL and in the process of picking this up from scratch to solve a problem.

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

I have a source XML file that contains the following structure:-

<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>

其中有多个<DetailRecord>和多个<DetailSubRecord>.

我设法将一个XSL放在一起,该XSL将一个嵌套的多个DetailRecords集输出到一个平面文件,但是我一直不知道如何在XSL中引用地址记录的第二个嵌套级别.

I have managed to put together an XSL that outputs a single nested set of multiple DetailRecords to a flat file but I haven't been able to puzzle out how to refer to the 2nd nested level of address records in the XSL...

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

Here is my XSL so far:

<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>

推荐答案

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

XSLT is a functional language, not a procedural; what most newcomers to XSLT don't realise is that the XSLT processor automatically handles each node in the tree, in the order they appear in the source. Without a template to define what to do with each node however, nothing is output.

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

In most cases, you don't need to use <xsl:for-each> just to get the child elements processed, this is already done for you, you just need to define a template that describes how you want each element to be output. Like this:

<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>

第一个模板中的<xsl:apply-templates />只是告诉XSLT处理器处理子元素,然后再添加记录计数.

The <xsl:apply-templates /> in the first template just tells the XSLT processor to deal with the child elements, after which it adds in the record count.

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

The second template handles any element with the three names in it's match atrtibute, and in each case outputs the content (.) concatenated with a new line.

当前形式的第三个模板实际上是多余的,处理器仍然可以这样做,但是您可以用更有用的内容替换该注释.

The third template in it's current form is actually superfluous, the processor will do that anyway, but you can replace that comment with something more useful.

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

You'll notice this doesn't give any information on how to handle a DetailRecord element; because all you want to do is process it's children, you don't need to specify anything, as that's taken as a given.

这篇关于如何使用模板遍历嵌套的XML结构的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆