【发布时间】:2017-08-25 18:01:14
【问题描述】:
我正在尝试转换一个多实例 XML 文件,其中一个父节点可能有 2 个或更多相同类型的子节点。
基本上,我有这种类型的 XML 文件:
<?xml version='1.0' encoding='UTF-8'?>
<Report_Data>
<Report_Entry>
<field1>Record1_field1</field1>
<field2>Record1_field2</field2>
<field3>Record1_field3</field3>
<Report_SubEntry>
<subField1>Record_1subfield1</subField1>
<subField2>Record_1subfield2</subField2>
<subField3>Record_1subfield3</subField3>
</Report_SubEntry>
<Report_SubEntry>
<subField1>Record1_subfield1_subEntry2</subField1>
<subField2>Record1_subfield2_subEntry2</subField2>
<subField3>Record1_subfield3_subEntry2</subField3>
</Report_SubEntry>
</Report_Entry>
<Report_Entry>
<field1>Record2_field1</field1>
<field2>Record2_field2</field2>
<field3>Record2_field3</field3>
<Report_SubEntry>
<subField1>Record2_subfield1</subField1>
<subField2>Record2_subfield2</subField2>
<subField3>Record2_subfield3</subField3>
</Report_SubEntry>
</Report_Entry>
</Report_Data>
XSLT 函数必须可重用于类似结构的 XML 文件,而不必为所有可能的子条目类型硬编码循环或条件。
这是我的 XSLT:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
exclude-result-prefixes="xs this ws">
<xsl:output method="text" encoding="UTF-8" media-type="text/plain"/>
<xsl:strip-space elements="*"/>
<xsl:param name="delimiter" select="'§'" />
<xsl:param name="quote" select="''" />
<xsl:param name="break" select="'
'" />
<!--
List of Fields to be included in final CSV.
!! Use only XPATH node names with prefixes. !!
If prefixes are to be removed from the header, update the
-->
<xsl:variable name="fieldArray">
<field>field1</field>
<field>field2</field>
<field>field3</field>
<field>subField1</field>
<field>subField2</field>
<field>subField3</field>
</xsl:variable>
<xsl:param name="fields" select="document('')/*/xsl:variable[@name='fieldArray']/*" />
<xsl:template match="//Report_Entry">
<!-- output the header row -->
<xsl:for-each select="$fields">
<xsl:if test="position() != 1">
<xsl:value-of select="$delimiter"/>
</xsl:if>
<xsl:value-of select="." />
</xsl:for-each>
<!-- output newline -->
<xsl:text>
</xsl:text>
<xsl:apply-templates select="Report_Entry"/>
</xsl:template>
<xsl:template match="//Report_Entry">
<xsl:variable name="currNode" select="." />
<!-- output the data row -->
<!-- loop over the field names and find the value of each one in the xml -->
<xsl:for-each select="$fields">
<xsl:if test="position() != 1">
<xsl:value-of select="$delimiter"/>
</xsl:if>
<xsl:value-of select="$quote" />
<xsl:variable name="child" select="$currNode[*]/*/*[name() = current()]" />
<xsl:variable name="childSecondLevel" select="$currNode[*]/*/*/*[name() = current()]" />
<xsl:variable name="childThirdLevel" select="$currNode[*]/*/*/*/*[name() = current()]" />
<xsl:choose>
<xsl:when test="count($child) > 0">
<xsl:value-of select="$child"/>
</xsl:when>
<xsl:when test="count($childSecondLevel) > 0">
<xsl:value-of select="$childSecondLevel"/>
</xsl:when>
<xsl:when test="count($childThirdLevel) > 0">
<xsl:value-of select="$childThirdLevel"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$currNode/*[name() = current()]" />
</xsl:otherwise>
</xsl:choose>
<xsl:value-of select="$quote" />
</xsl:for-each>
<!-- output newline -->
<xsl:value-of select="$break" />
</xsl:template>
</xsl:stylesheet>
我得到的输出是:
field1,field2,field3,subField1,subField2,subField3
Record1_field1,Record1_field2,Record1_field3,Record_1subfield1,Record_1subfield2,Record_1subfield3
Record2_field1,Record2_field2,Record2_field3,Record2_subfield1,Record2_subfield2,Record2_subfield3
但我需要的输出是:
field1,field2,field3,subField1,subField2,subField3
Record1_field1,Record1_field2,Record1_field3,Record_1subfield1,Record_1subfield2,Record_1subfield3
Record1_field1,Record1_field2,Record1_field3,Record_1subfield1_subEntry2,Record_1subfield2_subEntry2,Record_1subfield3_subEntry3
Record2_field1,Record2_field2,Record2_field3,Record2_subfield1,Record2_subfield2,Record2_subfield3
有人对解决这个问题有什么建议吗?
【问题讨论】: