首页 > 解决方案 > 使用 XSLT 将 XML 输出转换为新结构化的(其他元素)XML 时,如何在 XML 根标记中包含元素

问题描述

从 CRM 系统中,我得到一个包含所有元素的预定义结构的 XML。我的客户希望将生成的 XML 导入他们的 ERP 中,但是需要对其进行重组以适应他们的系统。我能够使用 XSLT 按照他们的意愿对其进行转换。但是,我无法向元素添加属性(有关更多详细信息,请参见下面的代码)。有人知道我如何在我的 XSLT 中对其进行硬编码,以便在 XML 中获得我想要的输出吗?

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="2.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns="com.cisag.app.sales.obj.SalesOrder" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

<xsl:import-schema schema-location="SALESORDER.xsd" 
namespace="com.cisag.app.sales.obj.SalesOrder"/>

<xsl:output method="xml" indent="yes" version="1.0" encoding="UTF-8"/>

<xsl:variable name="dateTime" select="//ActionDateTime"/>
<xsl:variable name="date" select="concat(substring($dateTime,9,2), '#', 
substring($dateTime,6,2), '#', substring($dateTime,1,4))"/>

<xsl:template match="/">

    <xsl:element name="semiramis">

        <xsl:element name="SalesOrder">

            <xsl:element name="Type">
                <xsl:element name="code">
                    <xsl:value-of select="105"/>
                </xsl:element>
            </xsl:element>

            <xsl:element name="invoicingPartyData">
                <xsl:element name="Partner">
                    <xsl:element name="number">
                        <xsl:value-of select="0"/>
                    </xsl:element>
                </xsl:element>
            </xsl:element>

            <xsl:element name="customerOrderData">
                <xsl:element name="purchaseOrder">
                    <xsl:value-of select="//WrntyID"/>
                </xsl:element>
                <xsl:element name="date">
                    <xsl:value-of select="$date"/>
                </xsl:element>
            </xsl:element>

            <xsl:element name="imp_description">
                <xsl:value-of select="//Remark"/>
            </xsl:element>

            <xsl:element name="customerData">
                <xsl:element name="CustomerPartner">
                    <xsl:element name="number">
                        <xsl:value-of select="//AccountExternalID"/>
                    </xsl:element>
                </xsl:element>
            </xsl:element>

            <xsl:element name="discountOriginType">
                <xsl:value-of select="('MANUAL')"/>
            </xsl:element>

            <xsl:element name="discounts">
                <xsl:element name="type">
                    <xsl:value-of select="('PERCENT_VALUE')"/>
                </xsl:element>
                <xsl:element name="value">
                    <xsl:value-of select="//DiscountPercentage"/>
                </xsl:element>
                <xsl:element name="DiscountType">
                    <xsl:element name="code">
                        <xsl:value-of select="200"/>
                    </xsl:element>
                </xsl:element>
            </xsl:element>

            <xsl:for-each select="//TransactionLine">
                <xsl:element name="Details">
                    <xsl:element name="Item">
                        <xsl:element name="number">
                            <xsl:value-of select="//ItemExternalID"/>
                        </xsl:element>
                    </xsl:element>
                    <xsl:element name="totalQuantity">
                        <xsl:element name="amount">
                            <xsl:value-of select="//UnitsQuantity"/>
                        </xsl:element>
                        <xsl:element name="Uom">
                            <xsl:element name="code">
                                <xsl:value-of 
select="//ItemTSABasiseinheit"/>
                            </xsl:element>
                        </xsl:element>
                    </xsl:element>
                    <xsl:element name="priceOriginType">
                        <xsl:value-of select="('MANUAL')"/>
                    </xsl:element>
                    <xsl:element name="grossPrice">
                        <xsl:element name="amount">
                            <xsl:value-of select="//TSAPreisvorRabatt"/>
                        </xsl:element>
                        <xsl:element name="Currency">
                            <xsl:element name="isoCode">
                                <xsl:value-of select="('EUR')"/>
                        </xsl:element>
                        </xsl:element>
                    </xsl:element>
                    <xsl:choose>
                        <xsl:when test="//TSAZeilenrabatt">
                            <xsl:element name="discounts">
                                <xsl:element name="type">
                                    <xsl:value-of select=" 
('PERCENT_VALUE')"/>
                                </xsl:element>
                                <xsl:element name="value">
                                    <xsl:value-of 
select="//TSAZeilenrabatt"/>
                                </xsl:element>
                                <xsl:element name="DiscountType">
                                    <xsl:element name="code">
                                        <xsl:value-of select="200"/>
                                    </xsl:element>
                                </xsl:element>
                            </xsl:element>
                        </xsl:when>
                    </xsl:choose>
                    <xsl:element name="imp_deliveryDate">
                        <xsl:element name="dateFrom">
                            <xsl:element name="specialValue">
                                <xsl:value-of select="('NONE')"/>
                            </xsl:element>
                            <xsl:element name="date">
                                <xsl:value-of select="//DeliveryDate"/>
                            </xsl:element>
                            <xsl:element name="timeZone">
                                <xsl:value-of select="('CET')"/>
                            </xsl:element>
                        </xsl:element>
                        <xsl:element name="dateUntil">
                            <xsl:element name="specialValue">
                                <xsl:value-of select="('NONE')"/>
                            </xsl:element>
                            <xsl:element name="date">
                                <xsl:value-of select="//TSALieferdatumBis"/>
                            </xsl:element>
                            <xsl:element name="timeZone">
                                <xsl:value-of select="('CET')"/>
                            </xsl:element>
                        </xsl:element>
                    </xsl:element>
                </xsl:element>
            </xsl:for-each>

        </xsl:element>

    </xsl:element>

</xsl:template>

</xsl:stylesheet>

这是我期望收到的:

<?xml version="1.0" encoding="UTF-8"?>
<semiramis xmlns="com.cisag.app.sales.obj.SalesOrder" 
xsi:schemaLocation="com.cisag.app.sales.obj.SalesOrder SALESORDER.xsd" 
created="2014-04-16T14:03:28.256Z" locale="en-US-XMLSchemaCompliant" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
nlsMode="SINGLE_LANGUAGE" dateTimeMode="NORMALIZED">
<SalesOrder xmlns="com.cisag.app.sales.obj.SalesOrder">
<Type>
  <code></code>
</Type>
<invoicingPartyData>
  <Partner>
    <number></number>
  </Partner>
</invoicingPartyData>
<customerOrderData>
  <purchaseOrder></purchaseOrder>
  <date>08#01#2019</date>
</customerOrderData>
<imp_description></imp_description>
<customerData>
  <CustomerPartner>
    <number></number>
  </CustomerPartner>
</customerData>
<discountOriginType>MANUAL</discountOriginType>
<discounts>
  <type>PERCENT_VALUE</type>
  <value>0</value>
  <DiscountType>
    <code>199</code>
  </DiscountType>
</discounts>
<Details>
  <Item>
    <number>010</number>
  </Item>
  <totalQuantity>
    <amount>900</amount>
    <Uom>
      <code></code>
    </Uom>
  </totalQuantity>
  <priceOriginType>MANUAL</priceOriginType>
  <grossPrice>
    <amount></amount>
    <Currency>
      <isoCode>EUR</isoCode>
    </Currency>
  </grossPrice>
  <discounts>
    <type>PERCENT_VALUE</type>
    <value>13</value>
    <DiscountType>
      <code></code>
    </DiscountType>
    <MeasureUom />
    <MeasureCurrency />
  </discounts>
  <imp_deliveryDate>
    <dateFrom>
      <specialValue>NONE</specialValue>
      <date>2019-01-08</date>
      <timeZone>CET</timeZone>
    </dateFrom>
    <dateUntil>
      <specialValue>NONE</specialValue>
      <date></date>
      <timeZone>CET</timeZone>
    </dateUntil>
  </imp_deliveryDate>
</Details>
</SalesOrder>
</semiramis>

这是我实际得到的:

<?xml version="1.0" encoding="utf-8"?>
<semiramis xmlns="com.cisag.app.sales.obj.SalesOrder">
<SalesOrder>
<Type>
  <code></code>
</Type>
<invoicingPartyData>
  <Partner>
    <number></number>
  </Partner>
</invoicingPartyData>
<customerOrderData>
  <purchaseOrder></purchaseOrder>
  <date>08#01#2019</date>
</customerOrderData>
<imp_description></imp_description>
<customerData>
  <CustomerPartner>
    <number></number>
  </CustomerPartner>
</customerData>
<discountOriginType>MANUAL</discountOriginType>
<discounts>
  <type>PERCENT_VALUE</type>
  <value>0</value>
  <DiscountType>
    <code>199</code>
  </DiscountType>
</discounts>
<Details>
  <Item>
    <number>010</number>
  </Item>
  <totalQuantity>
    <amount>900</amount>
    <Uom>
      <code></code>
    </Uom>
  </totalQuantity>
  <priceOriginType>MANUAL</priceOriginType>
  <grossPrice>
    <amount></amount>
    <Currency>
      <isoCode>EUR</isoCode>
    </Currency>
  </grossPrice>
  <discounts>
    <type>PERCENT_VALUE</type>
    <value>13</value>
    <DiscountType>
      <code></code>
    </DiscountType>
    <MeasureUom />
    <MeasureCurrency />
  </discounts>
  <imp_deliveryDate>
    <dateFrom>
      <specialValue>NONE</specialValue>
      <date>2019-01-08</date>
      <timeZone>CET</timeZone>
    </dateFrom>
    <dateUntil>
      <specialValue>NONE</specialValue>
      <date></date>
      <timeZone>CET</timeZone>
    </dateUntil>
  </imp_deliveryDate>
</Details>
</SalesOrder>
</semiramis>

标签: xmlxslt

解决方案


要将属性和命名空间声明添加到根semiramis元素,请替换:

<xsl:element name="semiramis">
... 
</xsl:element>

和:

<semiramis xmlns="com.cisag.app.sales.obj.SalesOrder" 
xsi:schemaLocation="com.cisag.app.sales.obj.SalesOrder SALESORDER.xsd" 
created="2014-04-16T14:03:28.256Z" locale="en-US-XMLSchemaCompliant" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
nlsMode="SINGLE_LANGUAGE" dateTimeMode="NORMALIZED">
...
</semiramis>"

如果其中一些属性需要动态评估其值,请使用属性值模板或显式xsl:attribute指令 - 例如:

<semiramis xmlns="com.cisag.app.sales.obj.SalesOrder" 
xsi:schemaLocation="com.cisag.app.sales.obj.SalesOrder SALESORDER.xsd" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
nlsMode="SINGLE_LANGUAGE" dateTimeMode="NORMALIZED">
    <xsl:attribute name="created">
        <xsl:value-of select="something-here"/>
    </xsl:attribute>
    <xsl:attribute name="locale">
        <xsl:value-of select="another-thing-here"/>
    </xsl:attribute>
    ...

注意:通常,最好使用文字结果元素而不是xsl:element. IOW,替换以下内容:

<xsl:element name="Type">
    <xsl:element name="code">
        <xsl:value-of select="105"/>
    </xsl:element>
</xsl:element>

和:

<Type>
  <code>105</code>
</Type>

xsl:element当元素的名称或命名空间需要在运行时动态确定时使用。


推荐阅读