首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >XSL的多嵌套循环将XML转换为未完全加载的表

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

Stack Overflow用户
提问于 2014-06-12 10:11:50
回答 1查看 101关注 0票数 1

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

代码语言:javascript
复制
<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文件

代码语言:javascript
复制
<?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>

我的预期结果

代码语言:javascript
复制
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,只需将其保留为空,否则它也应该是循环。

代码语言:javascript
复制
<RoleDetail>
    <Roles RoleType="Primary">
        <OccTitle SinceDay="17" SinceMonth="Nov" SinceYear="2009" OccCat="6">Thai</OccTitle>
    </Roles>
</RoleDetail>

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

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-06-12 11:53:37

正如@michael.hor257k在回答前一个问题时指出的那样:实际上,作为结果,您拥有的是一个由<for-each>循环跨越的矩阵。如果矩阵尺寸中至少有一个是空的,则产品将为空。

所以,我们必须“欺骗”一点。基本思想如下:对于矩阵的每个维度,我们提供一个选择表达式,如果存在维度元素,则选择它们,如果不存在单个维度条目,则提供一种虚拟条目。在您的例子中,Person适合这样做,因为我们知道,对于每个矩阵,我们正好有一个这个实体。我们创建一个变量person作为对这个基本元素的引用。

而不是写作,例如。

代码语言:javascript
复制
<xsl:for-each select="../../DateDetails/Date/DateValue">

我们写

代码语言:javascript
复制
<xsl:for-each select="$person/DateDetails/Date/DateValue|$person[not ($person/DateDetails/Date/DateValue)]">

|之前的第一部分将返回所有现有日期。如果不存在日期,则此集将为空。|之后的第二部分将返回<Person>节点(正好是一个!)如果我们找不到日期的话。因此,如果没有日期,而不是零大小维度,您将得到一个大小为1的维度。

但是,为什么这在零尺寸的情况下起作用呢?它可以工作,因为随后试图提取虚拟元素的日期值数据将导致空字符串,这恰好是所需的默认值。为了确保不获取任何其他空白,我添加了normalize-space()调用。

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

这是XSLT

代码语言:javascript
复制
<?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)"/>)是唯一不包含任何进一步的节点名称或属性名称的选择。为了解决这个问题,我替换了语句

代码语言:javascript
复制
<xsl:variable name="occTitle" select="."/>

通过

代码语言:javascript
复制
<xsl:variable name="occTitle" select="self::OccTitle"/>
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/24181849

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档