XSLT,使用基于Attribute的值的映射表重命名元素

时间:2017-10-12 11:29:39

标签: xml xslt transformation

如何根据元素属性的映射表重命名元素?

我们非常感谢任何建议。 也许是XSLT 2.0模板并修改映射表以获得更好的解决方案?

非常感谢提前 托马斯

原始XML:

<transaction>
  <records type="1" >
      <record type="1" >
        <field number="1" >
            <item>223</item>
        </field>
        <field number="2" >
            <item>456</item>
        </field>
      </record>
  </records>

  <records type="14" >
      <record type="14" >
        <field number="1" >
            <item>777</item>
        </field>
        <field number="2" >
            <item>678</item>
        </field>
      </record>

      <record type="14" >
        <field number="1" >
            <item>555</item>
        </field>
      </record>
  </records>
</transaction>

映射表:

<xsl:stylesheet>
  <mapping type="1" from="record" to="first-record">
      <map number="1" from="field" to="great-field"/>
      <map number="2" from="field" to="good-field"/>
  </mapping>

  <mapping type="14" from="record" to="real-record">
      <map number="1" from="field" to="my-field"/>
      <map number="2" from="field" to="other-field"/>
  </mapping>     
</xsl:stylesheet>

转型后的结果:

<transaction>
  <records type="1" >
      <first-record type="1" >
        <great-field number="1" >
            <item >223</item>
        </great-field>
        <good-field number="2" >
            <item >456</item>
        </good-field>
      </first-record>
  </records>

  <records type="14" >
      <real-record type="14" >
        <my-field number="1" >
            <item >777</item>
        </my-field>
        <other-field number="2" >
            <item >678</item>
        </other-field>
      </real-record>

      <real-record type="14" >
        <my-field number="1" >
            <item >555</item>
        </my-field>
      </real-record>
  </records>
</transaction>

1 个答案:

答案 0 :(得分:1)

这是一个XSLT 3.0样式表(可执行Saxon 9.8任何版本或Altova XMLSpy / Raptor 2017或2018),它将映射转换为XSLT 3.0样式表,然后使用XPath 3.1中的transform函数执行它:

<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"/>
            <map number="2" from="field" to="good-field"/>
        </mapping>

        <mapping type="14" from="record" to="real-record">
            <map number="1" from="field" to="my-field"/>
            <map number="2" from="field" to="other-field"/>
        </mapping>  
    </xsl:param>

    <xsl:namespace-alias stylesheet-prefix="axsl" result-prefix="xsl"/>

    <xsl:variable name="stylesheet">
        <axsl:stylesheet version="3.0">
            <axsl:mode name="transform" on-no-match="shallow-copy"/>
            <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="{@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="$stylesheet"></xsl:message>
        <xsl:sequence select="transform(map { 'source-node' : ., 'stylesheet-node' : $stylesheet , 'initial-mode' : xs:QName('transform') })?output"/>
    </xsl:template>

</xsl:stylesheet>

删除或注释<xsl:message select="$stylesheet"></xsl:message>,只显示生成的样式表代码。

当然,将映射转换为XSLT样式表的方法也可以与XSLT 2.0一起使用,但是您需要从XSLT外部运行创建的样式表,例如: Java或C#或在编辑器中手动完成。