【问题标题】:XSLT, Grouping Elements using mapping table based on attribute's valueXSLT,使用基于属性值的映射表对元素进行分组
【发布时间】:2017-10-27 22:00:57
【问题描述】:

基于以下问题: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>

任何建议将不胜感激。 提前感谢您的努力。

【问题讨论】:

    标签: xml xslt


    【解决方案1】:

    我已尝试修改该代码,我认为它目前为您的示例数据和映射提供了所需的 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>
    

    我目前不确定如果有一个 records 至少有一个孩子但没有其他孩子的映射,你想要或以上会产生什么样的输出。

    【讨论】:

    • 嗨,马丁,非常感谢您的热心帮助。我会立即测试你的模板。
    • 您好 Martin,您是 XSLT 魔术师 :-) 结果正是我想要的!我不知道你怎么这么快就生成了这么复杂的模板!!十分感谢您的支持。上帝保佑你和你的家人。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-11-06
    • 1970-01-01
    • 2015-09-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多