从祖先打印子节点
Print child nodes from ancestor
<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 部分不是必需的,但在看到结果时对我很有帮助。
您的 XSLT 的问题在于,当您想为每个 "Child Field".
创建一个条目时,它只会在 table 中为每个 "Grandpa Field" 创建一行
如果您所有的 XML 看起来都像这个例子,那么最简单的事情就是用 xsl:foreach
遍历每个 "Child field" 并在那个位置创建 table 行级别,如下所示:
<?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 变得比您的示例更复杂,您将需要比这更复杂的方法。例如,如果每个条目都不是 Grandpa/Son/Child,而是层次结构中有时有不同数量的级别(例如,有时只是 Son/Child,或者可能有些爷爷的儿子没有 children) 那么这个 XSLT 示例将忽略这些条目。
我会推荐以下方法。
- 查找所有叶
<Record>
元素(不包含任何其他记录的元素)。这很简单://Record[not(Record)]
.
- 对于它们中的每一个,输出它们的所有祖先,用
|
分隔,然后换行。
下面的简单转换正是这样做的:
<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>
</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
<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 部分不是必需的,但在看到结果时对我很有帮助。
您的 XSLT 的问题在于,当您想为每个 "Child Field".
创建一个条目时,它只会在 table 中为每个 "Grandpa Field" 创建一行如果您所有的 XML 看起来都像这个例子,那么最简单的事情就是用 xsl:foreach
遍历每个 "Child field" 并在那个位置创建 table 行级别,如下所示:
<?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 变得比您的示例更复杂,您将需要比这更复杂的方法。例如,如果每个条目都不是 Grandpa/Son/Child,而是层次结构中有时有不同数量的级别(例如,有时只是 Son/Child,或者可能有些爷爷的儿子没有 children) 那么这个 XSLT 示例将忽略这些条目。
我会推荐以下方法。
- 查找所有叶
<Record>
元素(不包含任何其他记录的元素)。这很简单://Record[not(Record)]
. - 对于它们中的每一个,输出它们的所有祖先,用
|
分隔,然后换行。
下面的简单转换正是这样做的:
<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>
</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