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

XSL使用多嵌套循环将XML转换为未完全加载的表,xml,xslt,Xml,Xslt,谢谢你 ,现在我可以通过XSLT将xml转换为表,但是,当我再添加一个嵌套循环时,结果没有完全加载,我不确定出了什么问题 数据XML <Records> <Person id="756252" date="15-Oct-2014"> <Gender>Male</Gender> <NameDetails> <Name NameType="Primary Name">

谢谢你 ,现在我可以通过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>
现在的问题是,由于第二个人的RoleDetail缺失,最后两行没有显示出来

对于数据,下面的节点可能在XML数据文件中,也可能不在XML数据文件中,如果该节点不是在XML中,请将其保留为空,否则它也应为循环

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

泰国人
**它将有大约35个像这样的可选元素。。
非常感谢@michael.hor257k在回答前面的问题时已经指出:您实际得到的结果是一个由
循环构成的矩阵。如果至少有一个矩阵维度为空,则乘积将为空

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

而不是写作

<xsl:for-each select="../../DateDetails/Date/DateValue">
编辑

正如@michael.hor257k(谢谢!)所建议的那样,如果找不到标题,则需要采取一些措施,避免意外输出
$person
的文本节点。问题的原因是,标题名(
)的提取是唯一不包含任何进一步的节点名或属性名选择的提取。为了解决这个问题,我替换了声明

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



+1,做得很好。我打算发布一些非常类似的东西,除了使用默认节点集1作为“虚拟节点”。但我更喜欢你的方法。我认为您应该做一个更正:
。否则,该单元格将充满来自该用户所有文本节点的垃圾。@Marcus Rickert感谢您耐心的解释!太酷了!还有一个后续问题:)当我执行代码时,我在最后两行“OccTitle”列(11)中得到了“Male Peter Lai”。我试图调试,似乎是在第一次执行到Person[2]“它跳回”然后是“give me”Male Peter Lai“我不明白为什么会这样。现在我很困惑,可能是我没有完全理解您的代码……:(编辑后是否包含更正?
<xsl:for-each select="../../DateDetails/Date/DateValue">
<xsl:for-each select="$person/DateDetails/Date/DateValue|$person[not ($person/DateDetails/Date/DateValue)]">
<?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>
<xsl:variable name="occTitle" select="."/>
<xsl:variable name="occTitle" select="self::OccTitle"/>