XSL的多嵌套循环将XML转换为Table未完全加载

时间:2014-06-12 10:11:51

标签: xml xslt

谢谢 multi nested loops by XSL to convert a XML to Table How to use XSLT to convert a XML to Table [CODE UPDATED 11/6] ,现在我可以通过XSLT将xml转换为表,但是当我添加一个嵌套循环时,结果没有完全加载,我不确定出了什么问题。

数据XML

<Records>
    <Person id="756252" date="15-Oct-2014">
        <Gender>Male</Gender>
        <NameDetails>
            <Name NameType="Primary Name">
                <NameValue>
                    <FirstName>Ken</FirstName>
                    <Surname>Wu</Surname>
                </NameValue>
            </Name>
            <Name NameType="AKA">
                <NameValue>
                    <FirstName>Kenneth</FirstName>
                    <Surname>Wu</Surname>
                </NameValue>
            </Name>
            <Name NameType="AKA2">
                <NameValue>
                    <FirstName>CAN</FirstName>
                    <Surname>Wu</Surname>
                </NameValue>
            </Name>
        </NameDetails>
        <Descriptions>
            <Description Description1="11" Description2="12" Description3="13"/>
            <Description Description1="21" Description2="22" Description3="23"/>
            <Description Description1="31" Description2="32" Description3="33"/>
        </Descriptions>
        <RoleDetail>
            <Roles RoleType="Primary">
                <OccTitle SinceDay="17" SinceMonth="Nov" SinceYear="2009" OccCat="6">Thai</OccTitle>
            </Roles>
        </RoleDetail>
        <DateDetails>
        <Date DateType="Date of Birth">
            <DateValue Year="1990" />
            <DateValue Year="1991" />
        </Date>
        <Date DateType="Date of Issue">
            <DateValue Year="2000" />
            <DateValue Year="2001" />
        </Date>
        </DateDetails>
    </Person>
    <Person id="253555" date="14-Oct-2014">
        <Gender>Male</Gender>
        <NameDetails>
            <Name NameType="Primary Name">
                <NameValue>
                    <FirstName>Peter</FirstName>
                    <Surname>Lai</Surname>
                </NameValue>
            </Name>
        </NameDetails>
        <Descriptions>
            <Description Description1="11" Description2="12" Description3="13"/>
            <Description Description1="21" Description2="22"/>
        </Descriptions>
        <Date DateType="Date of Birth">
            <DateValue Year="1992" />
        </Date>
    </Person>
</Records>

XSLT文件

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="/">
        <html>
            <head>
                <title>Records</title>
            </head>
            <body>
                <table border="1">
                    <tr>
                        <th>ID</th>
                        <th>Date</th>
                        <th>Gender</th>
                        <th>NameType</th>
                        <th>FirstName</th>
                        <th>SurName</th>
                        <th>Description1</th>
                        <th>Description2</th>
                        <th>Description3</th>
                        <th>RoleType</th>
                        <th>OccTitle</th>
                        <th>SinceDay</th>
                        <th>SinceMonth</th>
                        <th>DateType</th>
                        <th>Year</th>
                    </tr>
                    <xsl:for-each select="Records/Person/NameDetails/Name">
                        <xsl:variable name="name" select="."/>
                        <xsl:for-each select="../../DateDetails/Date/DateValue">
                            <xsl:variable name="dateval" select="."/>
                            <xsl:for-each select="../../../RoleDetail/Roles/OccTitle">
                                <xsl:variable name="occTitle" select="."/>
                                <xsl:for-each select="../../../Descriptions/Description">
                                    <tr>
                                        <td>
                                            <xsl:value-of select="../../@id"/>
                                        </td>
                                        <td>
                                            <xsl:value-of select="../../@date"/>
                                        </td>
                                        <td>
                                            <xsl:value-of select="../../Gender"/>
                                        </td>
                                        <td>
                                            <xsl:value-of select="$name/@NameType"/>
                                        </td>
                                        <td>
                                            <xsl:value-of select="$name/NameValue/FirstName"/>
                                        </td>
                                        <td>
                                            <xsl:value-of select="$name/NameValue/Surname"/>
                                        </td>
                                        <td>
                                            <xsl:value-of select="@Description1"/>
                                        </td>
                                        <td>
                                            <xsl:value-of select="@Description2"/>
                                        </td>
                                        <td>
                                            <xsl:value-of select="@Description3"/>
                                        </td>
                                        <td>
                                            <xsl:value-of select="$occTitle/../@RoleType"/>
                                        </td>
                                        <td>
                                            <xsl:value-of select="$occTitle"/>
                                        </td>
                                        <td>
                                            <xsl:value-of select="$occTitle/@SinceDay"/>
                                        </td>
                                        <td>
                                            <xsl:value-of select="$occTitle/@SinceMonth"/>
                                        </td>
                                        <td>
                                            <xsl:value-of select="$dateval/../@DateType"/>
                                        </td>
                                        <td>
                                            <xsl:value-of select="$dateval/@Year"/>
                                        </td>
                                    </tr>
                                </xsl:for-each>
                            </xsl:for-each>
                        </xsl:for-each>
                    </xsl:for-each>
                </table>
            </body>
        </html>
    </xsl:template>
</xsl:stylesheet>

我的预期结果

ID     |Date        |Gender |NameType     |FirstName |SurName |Description1 |Description2 |Description3 |RoleType |OccTitle |SinceDay |SinceMonth |DateType      |Year 
756252 |15-Oct-2014 |Male   |Primary Name |Ken       |Wu      |11           |12           |13           |Primary  |Thai     |17       |Nov        |Date of Birth |1990 
756252 |15-Oct-2014 |Male   |Primary Name |Ken       |Wu      |21           |22           |23           |Primary  |Thai     |17       |Nov        |Date of Birth |1990 
756252 |15-Oct-2014 |Male   |Primary Name |Ken       |Wu      |31           |32           |33           |Primary  |Thai     |17       |Nov        |Date of Birth |1990 
756252 |15-Oct-2014 |Male   |Primary Name |Ken       |Wu      |11           |12           |13           |Primary  |Thai     |17       |Nov        |Date of Birth |1991 
756252 |15-Oct-2014 |Male   |Primary Name |Ken       |Wu      |21           |22           |23           |Primary  |Thai     |17       |Nov        |Date of Birth |1991 
756252 |15-Oct-2014 |Male   |Primary Name |Ken       |Wu      |31           |32           |33           |Primary  |Thai     |17       |Nov        |Date of Birth |1991 
756252 |15-Oct-2014 |Male   |Primary Name |Ken       |Wu      |11           |12           |13           |Primary  |Thai     |17       |Nov        |Date of Issue |2000 
756252 |15-Oct-2014 |Male   |Primary Name |Ken       |Wu      |21           |22           |23           |Primary  |Thai     |17       |Nov        |Date of Issue |2000 
756252 |15-Oct-2014 |Male   |Primary Name |Ken       |Wu      |31           |32           |33           |Primary  |Thai     |17       |Nov        |Date of Issue |2000 
756252 |15-Oct-2014 |Male   |Primary Name |Ken       |Wu      |11           |12           |13           |Primary  |Thai     |17       |Nov        |Date of Issue |2001 
756252 |15-Oct-2014 |Male   |Primary Name |Ken       |Wu      |21           |22           |23           |Primary  |Thai     |17       |Nov        |Date of Issue |2001 
756252 |15-Oct-2014 |Male   |Primary Name |Ken       |Wu      |31           |32           |33           |Primary  |Thai     |17       |Nov        |Date of Issue |2001 
756252 |15-Oct-2014 |Male   |AKA          |Kenneth   |Wu      |11           |12           |13           |Primary  |Thai     |17       |Nov        |Date of Birth |1990 
756252 |15-Oct-2014 |Male   |AKA          |Kenneth   |Wu      |21           |22           |23           |Primary  |Thai     |17       |Nov        |Date of Birth |1990 
756252 |15-Oct-2014 |Male   |AKA          |Kenneth   |Wu      |31           |32           |33           |Primary  |Thai     |17       |Nov        |Date of Birth |1990 
756252 |15-Oct-2014 |Male   |AKA          |Kenneth   |Wu      |11           |12           |13           |Primary  |Thai     |17       |Nov        |Date of Birth |1991 
756252 |15-Oct-2014 |Male   |AKA          |Kenneth   |Wu      |21           |22           |23           |Primary  |Thai     |17       |Nov        |Date of Birth |1991 
756252 |15-Oct-2014 |Male   |AKA          |Kenneth   |Wu      |31           |32           |33           |Primary  |Thai     |17       |Nov        |Date of Birth |1991 
756252 |15-Oct-2014 |Male   |AKA          |Kenneth   |Wu      |11           |12           |13           |Primary  |Thai     |17       |Nov        |Date of Issue |2000 
756252 |15-Oct-2014 |Male   |AKA          |Kenneth   |Wu      |21           |22           |23           |Primary  |Thai     |17       |Nov        |Date of Issue |2000 
756252 |15-Oct-2014 |Male   |AKA          |Kenneth   |Wu      |31           |32           |33           |Primary  |Thai     |17       |Nov        |Date of Issue |2000 
756252 |15-Oct-2014 |Male   |AKA          |Kenneth   |Wu      |11           |12           |13           |Primary  |Thai     |17       |Nov        |Date of Issue |2001 
756252 |15-Oct-2014 |Male   |AKA          |Kenneth   |Wu      |21           |22           |23           |Primary  |Thai     |17       |Nov        |Date of Issue |2001 
756252 |15-Oct-2014 |Male   |AKA          |Kenneth   |Wu      |31           |32           |33           |Primary  |Thai     |17       |Nov        |Date of Issue |2001 
756252 |15-Oct-2014 |Male   |AKA2         |CAN       |Wu      |11           |12           |13           |Primary  |Thai     |17       |Nov        |Date of Birth |1990 
756252 |15-Oct-2014 |Male   |AKA2         |CAN       |Wu      |21           |22           |23           |Primary  |Thai     |17       |Nov        |Date of Birth |1990 
756252 |15-Oct-2014 |Male   |AKA2         |CAN       |Wu      |31           |32           |33           |Primary  |Thai     |17       |Nov        |Date of Birth |1990 
756252 |15-Oct-2014 |Male   |AKA2         |CAN       |Wu      |11           |12           |13           |Primary  |Thai     |17       |Nov        |Date of Birth |1991 
756252 |15-Oct-2014 |Male   |AKA2         |CAN       |Wu      |21           |22           |23           |Primary  |Thai     |17       |Nov        |Date of Birth |1991 
756252 |15-Oct-2014 |Male   |AKA2         |CAN       |Wu      |31           |32           |33           |Primary  |Thai     |17       |Nov        |Date of Birth |1991 
756252 |15-Oct-2014 |Male   |AKA2         |CAN       |Wu      |11           |12           |13           |Primary  |Thai     |17       |Nov        |Date of Issue |2000 
756252 |15-Oct-2014 |Male   |AKA2         |CAN       |Wu      |21           |22           |23           |Primary  |Thai     |17       |Nov        |Date of Issue |2000 
756252 |15-Oct-2014 |Male   |AKA2         |CAN       |Wu      |31           |32           |33           |Primary  |Thai     |17       |Nov        |Date of Issue |2000 
756252 |15-Oct-2014 |Male   |AKA2         |CAN       |Wu      |11           |12           |13           |Primary  |Thai     |17       |Nov        |Date of Issue |2001 
756252 |15-Oct-2014 |Male   |AKA2         |CAN       |Wu      |21           |22           |23           |Primary  |Thai     |17       |Nov        |Date of Issue |2001 
756252 |15-Oct-2014 |Male   |AKA2         |CAN       |Wu      |31           |32           |33           |Primary  |Thai     |17       |Nov        |Date of Issue |2001 
253555 |14-Oct-2014 |Male   |Primary Name |Peter     |Lai     |11           |12           |13           |         |         |         |           |Date of Issue |1992
253555 |14-Oct-2014 |Male   |Primary Name |Peter     |Lai     |21           |22           |             |         |         |         |           |Date of Issue |1992

现在问题是,由于第二人失踪了RoleDetail,最后两行没有显示

对于数据,下面的节点可能会或可能不会进入(XML数据文件),如果此节点不是XML格式,只需将其留空,否则它也应该循环。

<RoleDetail>
    <Roles RoleType="Primary">
        <OccTitle SinceDay="17" SinceMonth="Nov" SinceYear="2009" OccCat="6">Thai</OccTitle>
    </Roles>
</RoleDetail>

**它将有大约35个这样的可选元素.. 非常感谢

1 个答案:

答案 0 :(得分:2)

正如@ michael.hor257k已经在你上一个问题的答案中指出的那样:你实际得到的结果是你的<for-each>循环所跨越的矩阵。如果至少一个矩阵尺寸为空,则产品将为空。

所以,我们必须&#34;欺骗&#34;一点点。基本思想如下:对于矩阵的每个维度,我们提供一个选择表达式,如果它们存在则选择维度元素如果不存在单个维度条目,则加上一种虚拟条目。在您的情况下,Person适用于此,因为我们知道每个矩阵只有一次出现此实体。我们创建一个变量person作为对这个基本元素的引用。

而不是写作,例如

<xsl:for-each select="../../DateDetails/Date/DateValue">
我们写

<xsl:for-each select="$person/DateDetails/Date/DateValue|$person[not ($person/DateDetails/Date/DateValue)]">

|之前的第一部分将返回所有现有日期。如果没有日期,则此设置为空。如果我们没有找到任何日期,|之后的第二部分将返回<Person>节点(恰好是一个!)。因此,如果没有日期,而不是零尺寸尺寸,您将获得尺寸为1的尺寸。

但是,为什么这个尺寸为零尺寸的情况呢?它起作用,因为随后尝试提取例如虚拟元素的日期值数据将导致空字符串恰好是所需的默认值。为了确保我们没有获得任何其他空白区域,我添加了normalize-space()次来电。

请注意,您实际上还可以通过<choose>块替换变量赋值来为零大小维度提供默认值。

这是XSLT

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet 
    version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" />
  <xsl:template match="/">
    <html>
      <head>
        <title>Records</title>
      </head>
      <body>
        <table border="1">
          <tr>
            <th>ID</th>
            <th>Date</th>
            <th>Gender</th>
            <th>NameType</th>
            <th>FirstName</th>
            <th>SurName</th>
            <th>Description1</th>
            <th>Description2</th>
            <th>Description3</th>
            <th>RoleType</th>
            <th>OccTitle</th>
            <th>SinceDay</th>
            <th>SinceMonth</th>
            <th>DateType</th>
            <th>Year</th>
          </tr>
          <xsl:for-each select="Records/Person">
            <xsl:variable name="person" select="."/>
            <xsl:for-each select="$person/NameDetails/Name">
              <xsl:variable name="name" select="."/>
              <xsl:for-each select="$person/DateDetails/Date/DateValue|$person[not ($person/DateDetails/Date/DateValue)]">
                <xsl:variable name="dateval" select="."/>
                <xsl:for-each select="$person/RoleDetail/Roles/OccTitle|$person[not ($person/RoleDetail/Roles/OccTitle)]">
                  <xsl:variable name="occTitle" select="self::OccTitle"/>
                  <xsl:for-each select="$person/Descriptions/Description|$person[not ($person/Descriptions/Description)]">
                    <tr>
                      <td>
                        <xsl:value-of select="normalize-space(../../@id)"/>
                      </td>
                      <td>
                        <xsl:value-of select="normalize-space(../../@date)"/>
                      </td>
                      <td>
                        <xsl:value-of select="normalize-space(../../Gender)"/>
                      </td>
                      <td>
                        <xsl:value-of select="normalize-space($name/@NameType)"/>
                      </td>
                      <td>
                        <xsl:value-of select="normalize-space($name/NameValue/FirstName)"/>
                      </td>
                      <td>
                        <xsl:value-of select="normalize-space($name/NameValue/Surname)"/>
                      </td>
                      <td>
                        <xsl:value-of select="normalize-space(@Description1)"/>
                      </td>
                      <td>
                        <xsl:value-of select="normalize-space(@Description2)"/>
                      </td>
                      <td>
                        <xsl:value-of select="normalize-space(@Description3)"/>
                      </td>
                      <td>
                        <xsl:value-of select="normalize-space($occTitle/../@RoleType)"/>
                      </td>
                      <td>
                        <xsl:value-of select="normalize-space($occTitle)"/>
                      </td>
                      <td>
                        <xsl:value-of select="normalize-space($occTitle/@SinceDay)"/>
                      </td>
                      <td>
                        <xsl:value-of select="normalize-space($occTitle/@SinceMonth)"/>
                      </td>
                      <td>
                        <xsl:value-of select="normalize-space($dateval/../@DateType)"/>
                      </td>
                      <td>
                        <xsl:value-of select="normalize-space($dateval/@Year)"/>
                      </td>
                    </tr>
                  </xsl:for-each>
                </xsl:for-each>
              </xsl:for-each>
            </xsl:for-each>
          </xsl:for-each>
        </table>
      </body>
    </html>
  </xsl:template>
</xsl:stylesheet>

修改

正如@ michael.hor257k所建议的那样(谢谢!)如果没有找到标题,就不必意外输出$person的文本节点。问题是由于标题名称(<xsl:value-of select="normalize-space($occTitle)"/>)的提取是唯一一个不包含节点名称或属性名称的进一步选择的名称。为了解决这个问题,我更换了语句

<xsl:variable name="occTitle" select="."/>

通过

<xsl:variable name="occTitle" select="self::OccTitle"/>