我有一个以下需要转换的XML结构:
<recordset rowCount="68" fieldNames="ITEM,ECL,LEAD_TIME" type="**coldfusion.sql.QueryTable**">
<field name="ITEM">
<string>ITEM_A</string>
<string>ITEM_B</string>
<string>ITEM_C</string>
</field>
<field name="REV">
<string>A</string>
<string>B</string>
<string>C</string>
</field>
<field name="LEAD_TIME">
<string>10</string>
<string>15</string>
<string>25</string>
</field>
</recordset>
分为:
<records>
<item_line>
<item>ITEM_A</item>
<rev>A</rev>
<lead_time>10</lead_time>
</item_line>
<item_line>
<item>ITEM_B</item>
<rev>B</rev>
<lead_time>15</lead_time>
</item_line>
<item_line>
<item>ITEM_C</item>
<rev>C</rev>
<lead_time>25</lead_time>
</item_line>
</records>
我对XSLT的了解非常有限......
提前谢谢!
答案 0 :(得分:4)
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>
<xsl:output method="xml" indent="yes" omit-xml-declaration="yes" />
<xsl:template match="/recordset">
<records>
<xsl:apply-templates select="field[@name='ITEM']/string" />
</records>
</xsl:template>
<xsl:template match="field[@name='ITEM']/string">
<xsl:variable name="currpos" select="position()" />
<item_line>
<item>
<xsl:value-of select="." />
</item>
<rev>
<xsl:value-of select="/recordset/field[@name='REV']/string[$currpos]" />
</rev>
<lead_time>
<xsl:value-of select="/recordset/field[@name='LEAD_TIME']/string[$currpos]" />
</lead_time>
</item_line>
</xsl:template>
</xsl:stylesheet>
使用<xsl:key>
:
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>
<xsl:output method="xml" indent="yes" omit-xml-declaration="yes" />
<xsl:key name="k_field" match="recordset/field" use="@name" />
<xsl:template match="/">
<records>
<xsl:apply-templates select="key('k_field', 'ITEM')/string" />
</records>
</xsl:template>
<xsl:template match="field[@name='ITEM']/string">
<xsl:variable name="currpos" select="position()" />
<item_line>
<item>
<xsl:value-of select="." />
</item>
<rev>
<xsl:value-of select="key('k_field', 'REV')/string[$currpos]" />
</rev>
<lead_time>
<xsl:value-of select="key('k_field', 'LEAD_TIME')/string[$currpos]" />
</lead_time>
</item_line>
</xsl:template>
</xsl:stylesheet>
答案 1 :(得分:2)
一种简单的方法:
<?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="//recordset">
<records>
<xsl:apply-templates select="field[@name = 'ITEM']/string"/>
</records>
</xsl:template>
<xsl:template match="string">
<xsl:variable name="loc" select="position()"/>
<item_line>
<item>
<xsl:value-of select="."/>
</item>
<rev>
<xsl:value-of select="//recordset/field[@name = 'REV']/string[position() = $loc]"/>
</rev>
<lead_time>
<xsl:value-of select="//recordset/field[@name = 'LEAD_TIME']/string[position() = $loc]"/>
</lead_time>
</item_line>
</xsl:template>
</xsl:stylesheet>
以下是比上面更复杂的xslt。它将允许您进一步扩展revTemplate和leadTimeTemplate,而不会使字符串模板混乱。
<?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="//recordset">
<records>
<xsl:apply-templates select="field[@name = 'ITEM']/string"/>
</records>
</xsl:template>
<xsl:template match="string">
<item_line>
<item>
<xsl:value-of select="."/>
</item>
<xsl:call-template name="revTemplate">
<xsl:with-param name="loc" select="position()"/>
</xsl:call-template>
<xsl:call-template name="leadTimeTemplate">
<xsl:with-param name="loc" select="position()"/>
</xsl:call-template>
</item_line>
</xsl:template>
<xsl:template name="revTemplate">
<xsl:param name="loc"/>
<rev>
<xsl:value-of select="//recordset/field[@name = 'REV']/string[position() = $loc]"/>
</rev>
</xsl:template>
<xsl:template name="leadTimeTemplate">
<xsl:param name="loc"/>
<rev>
<xsl:value-of select="//recordset/field[@name = 'LEAD_TIME']/string[position() = $loc]"/>
</rev>
</xsl:template>
</xsl:stylesheet>
答案 2 :(得分:2)
以下解决方案适用于任何字段名称和任意数量的字段。数据格式表明字段名称可能是动态的。它也不假设字段子节点将始终命名为“字符串”。 (名称“string”让我怀疑可能会出现其他数据类型。无论它们是否存在,此解决方案仍然有效。)
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:template match="/">
<records>
<!-- Just process the first field's children,
to get the list of line items -->
<xsl:apply-templates select="/recordset/field[1]/*"/>
</records>
</xsl:template>
<!-- Convert each field child to a line item -->
<xsl:template match="field/*">
<item_line>
<!-- Then query all the fields for the value at this position -->
<xsl:apply-templates select="/recordset/field">
<xsl:with-param name="pos" select="position()"/>
</xsl:apply-templates>
</item_line>
</xsl:template>
<xsl:template match="field">
<xsl:param name="pos"/>
<!-- Convert the field name to lower case -->
<xsl:element name="{translate(
@name,
'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
'abcdefghijklmnopqrstuvwxyz'
)}">
<xsl:value-of select="*[$pos]"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
如果您有任何问题,请与我们联系。
编辑:上述的简化版本:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:template match="/">
<records>
<xsl:for-each select="/recordset/field[1]/*">
<xsl:variable name="pos" select="position()" />
<item_line>
<xsl:apply-templates select="/recordset/field/*[$pos]" />
</item_line>
</xsl:for-each>
</records>
</xsl:template>
<xsl:template match="field/*">
<xsl:element name="{translate(
../@name,
'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
'abcdefghijklmnopqrstuvwxyz'
)}">
<xsl:value-of select="."/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>