从祖先打印子节点

时间:2015-01-31 04:42:11

标签: xml xslt-1.0

<Records> 
    <Record>
        <Field>Grandpa Field</Field>
        <Record>
            <Field>Son Field</Field>
                <Record>
            <Field>Child Field 1</Field>
            </Record>
            <Record>
                <Field>Child Field 2</Field>
            </Record>
        </Record>   
    </Record>
</Records>

基于这个XML结构并遵循教程,我是XSLT的新手,我创建了以下XLST转换文件:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:template match="Records">
    <html>
      <body>
        <table border="1">
          <tr bgcolor="#9acd32">
            <th>Grandpa Field</th>
            <th>Son Field</th>
            <th>Child Field</th>
          </tr>
          <tr>
            <td>
              <xsl:for-each select="Record">
                <xsl:value-of select="Field" />
              </xsl:for-each>
            </td>
            <td>
              <xsl:for-each select="Record/Record">
                <xsl:value-of select="Field" />
              </xsl:for-each>
            </td>
            <td>
              <xsl:for-each select="Record/Record/Record">
                <xsl:value-of select="Field" />
              </xsl:for-each>
            </td>
          </tr>
        </table>
      </body>
    </html>
  </xsl:template>
</xsl:stylesheet>

这给了我以下输出:

Grandpa Field |Son Field | Child Field 1Child Field 2

我需要得到的是我的最终输出:

Grandpa Field |Son Field | Child Field 1
Grandpa Field |Son Field | Child Field 2

任何想法都将不胜感激!请注意,HTML部分不是必需的,但在查看结果时对我有帮助。

2 个答案:

答案 0 :(得分:0)

您的XSLT的问题是,当您想要为每个“子域”输入一个条目时,它只为每个“爷爷字段”在表格中创建一行。

如果您的所有XML看起来都像这个示例,那么最简单的方法是使用xsl:foreach遍历每个“子字段”并在该级别创建表行,如下所示:

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

  <xsl:template match="Records">
    <html>
      <body>
        <table border="1">
          <tr bgcolor="#9acd32">
            <th>Grandpa Field</th>
            <th>Son Field</th>
            <th>Child Field</th>
          </tr>

          <xsl:for-each select="Record/Record/Record">

            <tr>
              <td>
                <xsl:value-of select="../../Field"/>
              </td>
              <td>
                <xsl:value-of select="../Field"/>
              </td>
              <td>
                <xsl:value-of select="Field"/>
              </td>
            </tr>

          </xsl:for-each>

        </table>
      </body>
    </html>
  </xsl:template>

</xsl:stylesheet>

但是,如果您的XML比示例中的更复杂,则需要比此更复杂的方法。例如,如果每个条目都不是爷爷/儿子/孩子,而是层次结构中有时会有不同数量的级别(例如,有时候只有儿子/孩子,或者爷爷的一些儿子没有孩子)那么这个XSLT示例将省略这些条目。

答案 1 :(得分:0)

我建议采用以下方法。

  1. 查找所有叶<Record>元素(不包含任何其他记录的元素)。这很简单://Record[not(Record)]
  2. 对于他们每个人,输出他们的所有祖先,用|分隔,然后输出换行符。
  3. 以下简单转换正是如此:

    <xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
        <xsl:output method="text" encoding="UTF-8" />
    
        <xsl:template match="/">
            <xsl:apply-templates select="//Record[not(Record)]" mode="line" />
        </xsl:template>
    
        <xsl:template match="Record" mode="line">
            <xsl:apply-templates select="ancestor-or-self::Record" />
            <xsl:if test="position() != last()"><xsl:text>&#xA;</xsl:text></xsl:if>
        </xsl:template>
    
        <xsl:template match="Record">
            <xsl:value-of select="Field" />
            <xsl:if test="position() != last()"><xsl:text>|</xsl:text></xsl:if>
        </xsl:template>
    </xsl:transform>
    

    应用于您的样本输入,生成:

    Grandpa Field|Son Field|Child Field 1
    Grandpa Field|Son Field|Child Field 2
    

    请参阅:http://xsltransform.net/nc4NzQo