这是一个有点不优雅的解决方案,并且需要额外的工作来扩展到结构不同的数据集(尽管它适用于您的示例数据集中排列的任意数量的 serviceInfo 和 serviceRequest 元素)。它的优点是它涉及使用应用模板而不是 for-each。使用应用模板是最佳实践。另外,我不知道要使用正确的命名空间,所以我只是做了一些。
这个 XSLT
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:foi="http://www.foi.com"
xmlns:rdf="http://www.rdf.com"
exclude-result-prefixes="foi rdf"
version="2.0">
<!-- Identity template -->
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:variable name="newLine"><xsl:text>
</xsl:text></xsl:variable>
<xsl:template match="/">
<xsl:value-of select="$newLine"/><table><xsl:value-of select="$newLine"/>
<xsl:apply-templates select="//foi:creationDate"/>
</table><xsl:value-of select="$newLine"/>
</xsl:template>
<xsl:template match="foi:creationDate">
<xsl:variable name="resourceId" select="replace(../foi:servicing/@rdf:resource,'#','')"/>
<xsl:message>BAH <xsl:value-of select="$resourceId"/></xsl:message>
<tr><xsl:value-of select="$newLine"/>
<td><xsl:apply-templates/></td><xsl:value-of select="$newLine"/>
<td><xsl:apply-templates select="//foi:serviceName[parent::*[@rdf:ID=$resourceId]]"/></td><xsl:value-of select="$newLine"/>
<td><xsl:apply-templates select="//foi:problemCode[parent::*[@rdf:ID=$resourceId]]"/></td><xsl:value-of select="$newLine"/>
<td><xsl:apply-templates select="//foi:division[parent::*[@rdf:ID=$resourceId]]"/></td><xsl:value-of select="$newLine"/>
</tr><xsl:value-of select="$newLine"/>
</xsl:template>
<xsl:template match="foi:serviceName">
<xsl:apply-templates select="@* | node()" />
</xsl:template>
<xsl:template match="foi:problemCode">
<xsl:apply-templates select="@* | node()" />
</xsl:template>
<xsl:template match="foi:division">
<xsl:apply-templates select="@* | node()" />
</xsl:template>
</xsl:stylesheet>
应用于此 XML 文档时:(注意:我添加了一个根元素)
<root>
<foi:serviceInfo rdf:ID="SI1">
<foi:serviceName>Sewer</foi:serviceName>
<foi:problemCode>SI1</foi:problemCode>
<foi:division>Water</foi:division>
</foi:serviceInfo>
<foi:serviceInfo rdf:ID="SI2">
<foi:serviceName>Recycling</foi:serviceName>
<foi:problemCode>SI2</foi:problemCode>
<foi:division>Solid Waste</foi:division>
</foi:serviceInfo>
<foi:serviceRequest rdf:ID="R1">
<foi:creationDate>29 03 2013</foi:creationDate>
<foi:servicing rdf:resource="#SI1"/>
</foi:serviceRequest>
<foi:serviceRequest rdf:ID="R2">
<foi:creationDate>29 06 2013</foi:creationDate>
<foi:servicing rdf:resource="#SI2"/>
</foi:serviceRequest>
</root>
产生所需的结果:
<tr>
<td>29 03 2013</td>
<td>Sewer</td>
<td>SI1</td>
<td>Water</td>
</tr>
<tr>
<td>29 06 2013</td>
<td>Recycling</td>
<td>SI2</td>
<td>Solid Waste</td>
</tr>
</table>
简要说明:
- 抑制文本节点(文本节点的默认模板是输出它们;我们将通过 XSLT 文件末尾的特定模板输出它们)
- 处理 foi:creationDate 元素
- 在处理每个 foi:createDate 元素时,找到其父 rdf:resource 并将该值存储在变量中
- 然后处理每个适当的元素,通过查看文档中的所有元素(这就是“//”的意思),其父的 rdf:ID 与 rdf:resource 匹配(注意:如果有多个匹配的元素,这将输出多个值标准...您的数据集没有这样的多个元素;* 可能是 [也许应该是] foi:serviceName,但我想说明 * 的含义——选择任何元素并且 [] 中的内容区分哪些元素可以合格)
- 这也允许您在 serviceName 等元素中有子节点(不仅仅是文本节点)并处理这些节点(尽管现在处理正在复制到结果树)