基于以下问题:XSLT, Renaming Elements using mapping table based on Attribute's value
如何将未在映射表中定义的元素(此处为示例99和100)收集到名为“customRecords”的元素中?
源XML:
<transaction>
<records type="1" >
<record type="1" >
<field number="1" >
<item>223</item>
</field>
</record>
</records>
<records type="14" >
<record type="14" >
<field number="1" >
<item>777</item>
</field>
</record>
</records>
<records type="99" >
<record type="99" >
<field number="1" >
<item>123</item>
</field>
</record>
<record type="99" >
<field number="1" >
<item>765</item>
</field>
</record>
</records>
<records type="100" >
<record type="100" >
<field number="1" >
<item>456</item>
</field>
</record>
<record type="100" >
<field number="1" >
<item>121</item>
</field>
</record>
</records>
</transaction>
映射表:
<xsl:stylesheet>
<mapping type="1" from="record" to="first-record">
<map number="1" from="field" to="great-field"/>
</mapping>
<mapping type="14" from="record" to="real-record">
<map number="1" from="field" to="my-field"/>
</mapping>
</xsl:stylesheet>
目标XML:
<transaction>
<records type="1" >
<first-record type="1" >
<great-field number="1" >
<item >223</item>
</great-field>
</first-record>
</records>
<records type="14">
<real-record type="14" >
<my-field number="1" >
<item >777</item>
</my-field>
</real-record>
</records>
<customRecords>
<record type="99" >
<field number="1" >
<item>123</item>
</field>
</record>
<record type="99" >
<field number="1" >
<item>765</item>
</field>
</record>
<record type="100" >
<field number="1" >
<item>456</item>
</field>
</record>
<record type="100" >
<field number="1" >
<item>121</item>
</field>
</record>
</customRecords>
</transaction>
我们非常感谢任何建议。 在此先感谢您的努力。
答案 0 :(得分:1)
我已经尝试调整该代码,我认为它目前为您的示例数据和映射提供了所需的XML输出,尽管Saxon在生成的代码中发出了关于ambigious模板的警告,我认为它们暂时可以被忽略。
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:math="http://www.w3.org/2005/xpath-functions/math"
xmlns:axsl="http://www.w3.org/1999/XSL/Transform-alias"
exclude-result-prefixes="xs math axsl"
version="3.0">
<xsl:param name="mapping">
<mapping type="1" from="record" to="first-record">
<map number="1" from="field" to="great-field"/>
</mapping>
<mapping type="14" from="record" to="real-record">
<map number="1" from="field" to="my-field"/>
</mapping>
</xsl:param>
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:namespace-alias stylesheet-prefix="axsl" result-prefix="xsl"/>
<xsl:variable name="stylesheet">
<axsl:stylesheet version="3.0">
<axsl:variable name="mapping">
<xsl:copy-of select="$mapping/mapping"/>
</axsl:variable>
<axsl:key name="mapping" match="mapping" composite="yes" use="@from, @type"/>
<axsl:mode name="copy" on-no-match="shallow-copy"/>
<axsl:mode name="transform" on-no-match="shallow-copy"/>
<axsl:template match="/*" mode="transform">
<axsl:copy>
<axsl:apply-templates select="@*" mode="#current"/>
<axsl:apply-templates mode="#current"/>
<customElements>
<axsl:apply-templates select="*/*[not(key('mapping', (local-name(), @type), $mapping))]" mode="copy"/>
</customElements>
</axsl:copy>
</axsl:template>
<xsl:apply-templates select="$mapping/mapping" mode="xslt-modes"/>
<xsl:apply-templates select="$mapping/mapping" mode="xslt-code"/>
</axsl:stylesheet>
</xsl:variable>
<xsl:template match="mapping" mode="xslt-modes">
<axsl:mode name="transform-{position()}" on-no-match="shallow-copy"/>
</xsl:template>
<xsl:template match="mapping" mode="xslt-code">
<axsl:template match="/*/*[not(*[key('mapping', (local-name(), @type), $mapping)])]" mode="transform"/>
<axsl:template match="{@from}[@type = '{@type}']" mode="transform">
<axsl:element name="{@to}">
<axsl:apply-templates select="@* | node()" mode="transform-{position()}"/>
</axsl:element>
</axsl:template>
<xsl:apply-templates mode="xslt-code">
<xsl:with-param name="pos" select="position()"/>
</xsl:apply-templates>
</xsl:template>
<xsl:template match="map" mode="xslt-code">
<xsl:param name="pos"/>
<axsl:template match="{@from}[@number = '{@number}']" mode="transform-{$pos}">
<axsl:element name="{@to}">
<axsl:apply-templates select="@* | node()" mode="#current"/>
</axsl:element>
</axsl:template>
</xsl:template>
<xsl:template match="/">
<xsl:message select="serialize($stylesheet, map { 'indent' : true() })"/>
<xsl:sequence select="transform(map { 'source-node' : ., 'stylesheet-node' : $stylesheet , 'initial-mode' : xs:QName('transform') })?output"/>
</xsl:template>
</xsl:stylesheet>
我目前还不确定如果有records
的情况,你想要或者上面会产生什么样的输出,其中至少有一个孩子有一个映射但是对其他孩子没有。