Xml XSLT,使用基于属性值的映射表对元素进行分组

Xml XSLT,使用基于属性值的映射表对元素进行分组,xml,xslt,Xml,Xslt,基于以下问题: 这里如何将映射表中未定义的元素(如示例99和100)收集到名为customRecords的元素中 源XML: <transaction> <records type="1" > <record type="1" > <field number="1" > <item>223</item> </field> <

基于以下问题:

这里如何将映射表中未定义的元素(如示例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>
如有任何建议,将不胜感激。
提前感谢您的努力。

我已经尝试修改了该代码,我认为它目前为您的示例数据和映射提供了所需的XML输出。尽管Saxon发出了关于生成代码中模版模糊的警告,但我认为它们暂时可以忽略

<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>

我目前不确定,如果存在一个记录,其中至少有一个孩子有映射,但其他孩子没有映射,那么您想要或更高级别的输出将产生什么样的输出。

嗨,Martin,非常感谢您的帮助。我会立即测试你的模板。你好,Martin,你是XSLT魔术师:-结果正是我想要的!我不知道你怎么能如此快速地生成如此复杂的模板!!非常感谢你的支持。上帝保佑你和你的家人。