我有以下XML,需要按照下面“期望的输出”部分中的说明进行转换。
转换的要求是:
示例XML输入文件
<?xml version="1.0" encoding="UTF-8"?>
<workers>
<worker>
<name>sam</name>
<batch_id>1345</batch_id>
<dependents>
<name>sara</name>
</dependents>
<dependents>
<name>tom</name>
</dependents>
<dependents>
<name>harry</name>
</dependents>
<locations>
<place>ny</place>
<type>work</type>
</locations>
<locations>
<place>sfo</place>
<type>home</type>
</locations>
</worker>
</workers>
预期产量
<?xml version="1.0" encoding="UTF-8"?>
<workers>
<worker>
<name>sam</name>
<batch_id>1345</batch_id>
<dependents1>
<name>sara</name>
</dependents1>
<dependents_row1>1</dependents_row1>
<dependents2>
<name>tom</name>
</dependents2>
<dependents_row2>2</dependents_row2>
<dependents3>
<name>harry</name>
</dependents3>
<dependents_row3>3</dependents_row3>
<locations1>
<place>ny</place>
<type>work</type>
</locations1>
<locations_row1>1</locations_row1>
<locations2>
<place>sfo</place>
<type>home</type>
</locations2>
<locations_row2>2</locations_row2>
</worker>
</workers>
答案 0 :(得分:1)
您可以使用以下样式表(尽管有给定的设计疑问):
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" />
<!-- identity template -->
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*" />
</xsl:copy>
</xsl:template>
<xsl:template match="/workers/worker"> <!-- handles the sub-elements of the worker node -->
<xsl:copy>
<xsl:apply-templates select="*[not(self::dependents or self::locations)]" />
<xsl:apply-templates select="dependents" />
<xsl:apply-templates select="locations" />
</xsl:copy>
</xsl:template>
<xsl:template match="dependents|locations"> <!-- handles the addition of the position nodes -->
<xsl:element name="{concat(local-name(),position())}">
<xsl:copy-of select="*" />
</xsl:element>
<xsl:element name="{concat(local-name(),'_row',position())}">
<xsl:value-of select="position()" />
</xsl:element>
</xsl:template>
</xsl:stylesheet>
答案 1 :(得分:1)
一种不知道元素名称并且使用注释中建议的xsl:number
的通用解决方案是
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[some $sibling in (preceding-sibling::*, following-sibling::*) satisfies node-name($sibling) = node-name(.)]">
<xsl:variable name="index" as="xs:integer">
<xsl:number/>
</xsl:variable>
<xsl:element name="{name()}{$index}">
<xsl:apply-templates/>
</xsl:element>
<xsl:element name="{name()}_row{$index}">
<xsl:value-of select="$index"/>
</xsl:element>
</xsl:template>
</xsl:transform>
当然,您可以将match="*[some $sibling in (preceding-sibling::*, following-sibling::*) satisfies node-name($sibling) = node-name(.)]"
简化或简化为match="descendents | locations"
,如果已知元素和/或仅将某些元素作为目标。