感谢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个这样的可选元素。非常感谢
发布于 2014-06-12 11:53:37
正如@michael.hor257k在回答前一个问题时指出的那样:实际上,作为结果,您拥有的是一个由<for-each>循环跨越的矩阵。如果矩阵尺寸中至少有一个是空的,则产品将为空。
所以,我们必须“欺骗”一点。基本思想如下:对于矩阵的每个维度,我们提供一个选择表达式,如果存在维度元素,则选择它们,如果不存在单个维度条目,则提供一种虚拟条目。在您的例子中,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"/>https://stackoverflow.com/questions/24181849
复制相似问题