XSL转换可根据输入的属性动态生成输出XML

时间:2019-01-30 20:28:44

标签: xml xslt xslt-2.0

在此道歉,很抱歉,只有几个重要细节可以完全阐述我所遇到的问题,但这(应该是!)本质上是一个简单的XSLT问题。


我有以下3个XML文档(以作为其结构的示例):

<?xml version="1.0" encoding="UTF-8" ?>
<rabbitEnvelope>
    <action>YES</action>
    <logId>123</logId>
    <payload class="rabbit">
            <id>1</id>
            <name>Some Bunny</name>
            <easter>false</easter>
    </payload>
</rabbitEnvelope>

<?xml version="1.0" encoding="UTF-8" ?>
<bearEnvelope>
    <action>NO</action>
    <logId>456</logId>
    <payload class="bear">
            <type>Polar</type>
            <weight>655</weight>
    </payload>
</bearEnvelope>

<?xml version="1.0" encoding="UTF-8" ?>
<dogEnvelope>
    <action>MAYBE</action>
    <logId>789</logId>
    <payload class="dog">
            <goodboy>YES!</goodboy>
            <eats>Everything</eats>
        <canFetch>true</canFetch>
        <moniker>Fido</moniker>
    </payload>
</dogEnvelope>

我们将它们称为这3个不同XML文档的“ 经典版本”。

我的应用程序现在将收到其中的“ 新版本”,我需要编写XSL转换,以将新版本转换为经典版本。这些XML文档的新版本(再次作为示例)如下所示:

<?xml version="1.0" encoding="UTF-8" ?>
<envelope>
    <action>YES</action>
    <auditId>123</auditId>
    <payload class="rabbit">
        <id>1</id>
        <name>Some Bunny</name>
        <easter>false</easter>
    </payload>
</envelope>

<?xml version="1.0" encoding="UTF-8" ?>
<envelope>
    <action>NO</action>
    <auditId>456</auditId>
    <payload class="bear">
        <type>Polar</type>
        <weight>655</weight>
    </payload>
</envelope>

<?xml version="1.0" encoding="UTF-8" ?>
<envelope>
    <action>MAYBE</action>
    <auditId>789</auditId>
    <payload class="dog">
        <goodboy>YES!</goodboy>
        <eats>Everything</eats>
        <canFetch>true</canFetch>
        <moniker>Fido</moniker>
    </payload>
</envelope>

因此,在这些“新版本”中,最外面的XML元素总是 <envelope>元素。新版本的<action>元素与经典版本中的元素相同。新的/envelope/auditId与经典版本的<logId>/rabbitEnvelope/logId等)相同。并且/envelope/payload也与经典版本(/bearEnvelope/payload等)完全相同。

同样,我需要编写一个XSL转换,它将XML的新版本(<envelope>有效负载)转换为经典版本。

  • /envelope/payload/@class值确定经典版本的最外层元素的名称。因此为/envelope/payload/@class='rock',则其“经典”版本的最外层/根元素将为<rockEnvelope>
  • 我想将/envelope/action复制到/<rootElementEnvelope>/action。因此,如果/envelope/action='YES',则/<rootElementEnvelope>/action='YES'
  • 我想将/envelope/auditId value 复制到<rootElementEnvelope>/logId。因此,如果/envelope/auditId='123',则/<rootElementEnvelope>/logId='123'
  • 我想将整个 /envelope/payload复制到/<rootElementEnvelope>/payload

我在通用XSLT上的第一个刺探如下:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
    <xsl:template match="//envelope">
    <!-- The rabbitEnvelope element needs to be dynamically generated! -->
    <rabbitEnvelope>
        <action><xsl:value-of select="../action"/></action>
        <logId><xsl:value-of select="../auditId"/></logId>
        <payload class="???">
            <!-- All the XML from inside the source payload tag-->
        </payload>
    </rabbitEnvelope>
</xsl:template>      

但是,由于我的需求具有相同/共同的动态特性,这里还是存在一些问题。

  1. 由于<payload class=???>值确定转换后的/结果根标签是<rabbitEnvelope><bearEnvelope><dogEnvelope><rockEnvelope>(还是其他任何类型, 还有很多!),我不能只将<rabbitEnvelope>硬编码到我的XSLT中。
  2. 相信我对<action><xsl:value-of select="../action"/></action><logId><xsl:value-of select="../auditId"/></logId>的使用是正确的,但是如果您发现有问题,请告诉我!
  3. 我不确定如何生成输出/结果<payload/>标记,因为它只是输入XML中内容的直接副本,不能进行硬编码。

有什么想法可以根据我这里需求的动态性质来完成所需的转换?预先感谢!

1 个答案:

答案 0 :(得分:1)

怎么样:

XSLT 2.0(还与XSLT 1.0兼容)

.. toctree::
    :maxdepth: 1
    :titlesonly:

    myfile2
    myfile1