XSLT,使用基于属性值的映射表重命名元素 [英] XSLT, Renaming Elements using mapping table based on Attribute's value

查看:30
本文介绍了XSLT,使用基于属性值的映射表重命名元素的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

How to rename the elements according to a mapping table based on attribute's of the element?

任何建议将不胜感激.也许是 XSLT 2.0 模板并修改映射表以获得更好的解决方案?

Any suggestions would be much appreciated. Maybe a XSLT 2.0 template and modifying the mapping table for better solution?

非常感谢托马斯

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

推荐答案

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

Here is an XSLT 3.0 stylesheet (executable with Saxon 9.8 any edition or Altova XMLSpy/Raptor 2017 or 2018) that transforms the mapping into an XSLT 3.0 stylesheet and then executes it with the transform function from XPath 3.1:

<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>,它仅在其中显示生成的样式表代码.

Remove or comment out the <xsl:message select="$stylesheet"></xsl:message> which is only in there to show the produced stylesheet code.

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

Of course the approach to transform the mapping into an XSLT stylesheet can also be used with XSLT 2.0 but then you need to run the created stylesheet from outside XSLT with e.g. Java or C# or by hand in your editor.

这篇关于XSLT,使用基于属性值的映射表重命名元素的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆