Как добавить дополнительные корневые узлы для плохо сформированной структуры XML? - PullRequest
0 голосов
/ 02 ноября 2018

У нас есть ниже не правильно сформированный входной XML, исходящий из исходной системы.

<?xml version="1.0" encoding="UTF-8"?>
<ns0:invoiceOrder xmlns:ns0="http://cts.com"
               type="ABCD"
               businessDivision="X0"
               salesOrganization="XYZ10"
               Channel="Y0">
   <ns0:references>
      <ns0:key type="Source System">ABC</ns0:key>
      <ns0:relationship scheme="Customer" schemeAgency="APAC" role="Sell to">703760000</ns0:relationship>
      <ns0:document type="Purchase Order">AB123</ns0:document>
   </ns0:references>
   <ns0:notes>
      <ns0:note type="XY67" language="EN">package1</ns0:note>
   </ns0:notes>
   <ns0:orderLines>
      <ns0:orderLine>
         <ns0:identifiers>
            <ns0:identifier scheme="Item" schemeAgency="ABC">100411</ns0:identifier>
         </ns0:identifiers>
         <ns0:amounts>
            <ns0:amount type="credit Amount">274.50</ns0:amount>
         </ns0:amounts>
      </ns0:orderLine>
      <ns0:orderLine>
         <ns0:identifiers>
            <ns0:identifier scheme="Item" schemeAgency="ABC">140072</ns0:identifier>
         </ns0:identifiers>
         <ns0:amounts>
            <ns0:amount type="credit Amount">58.41</ns0:amount>
         </ns0:amounts>
      </ns0:orderLine>
   </ns0:orderLines>
   <ns0:terms>
      <ns0:term type="Reason Code">D19</ns0:term>
      <ns0:term type="Payment Terms">Y000</ns0:term>
   </ns0:terms>
   <ns0:billingInfo>
      <ns0:paymentMethod/>
   </ns0:billingInfo>
   <ns0:flags>
      <ns0:flag type="1099 Payment Flag">Y</ns0:flag>
   </ns0:flags>
   <ns0:dates>
      <ns0:date type="Proposed Invoice Date">2018-11-02</ns0:date>
   </ns0:dates>
</ns0:invoiceOrder>
<ns0:invoiceOrder xmlns:ns0="http://cts.com"
               type="ABCD"
               businessDivision="X0"
               salesOrganization="ABC10"
               Channel="Y0">
   <ns0:references>
      <ns0:key type="Source System">ABC</ns0:key>
      <ns0:relationship scheme="Customer" schemeAgency="APAC" role="Sell to">702390000</ns0:relationship>
      <ns0:document type="Purchase Order">AB123</ns0:document>
   </ns0:references>
   <ns0:notes>
      <ns0:note type="XY34" language="EN">package2</ns0:note>
   </ns0:notes>
   <ns0:orderLines>
      <ns0:orderLine>
         <ns0:identifiers>
            <ns0:identifier scheme="Item" schemeAgency="ABC">100411</ns0:identifier>
         </ns0:identifiers>
         <ns0:amounts>
            <ns0:amount type="Rebate Amount">76.25</ns0:amount>
         </ns0:amounts>
      </ns0:orderLine>
      <ns0:orderLine>
         <ns0:identifiers>
            <ns0:identifier scheme="Item" schemeAgency="ABC">140072</ns0:identifier>
         </ns0:identifiers>
         <ns0:amounts>
            <ns0:amount type="Rebate Amount">9.74</ns0:amount>
         </ns0:amounts>
      </ns0:orderLine>
   </ns0:orderLines>
   <ns0:terms>
      <ns0:term type="Reason Code">Y19</ns0:term>
      <ns0:term type="Payment Terms">Y000</ns0:term>
   </ns0:terms>
   <ns0:billingInfo>
      <ns0:paymentMethod/>
   </ns0:billingInfo>
   <ns0:flags>
      <ns0:flag type="1099 Payment Flag">Y</ns0:flag>
   </ns0:flags>
   <ns0:dates>
      <ns0:date type="Proposed Invoice Date">2018-11-02</ns0:date>
   </ns0:dates>
</ns0:invoiceOrder>

Я могу сделать вышеупомянутый xml также хорошо сформированным, если смогу добавить нижеприведенные теги к вышеуказанному вводу.

Начальные теги:

<ns0:Messages xmlns:ns0="http://sap.com/xi/XI/SplitAndMerge">
    <ns0:Message1>

Соответствующие конечные теги:

    </ns0:Message1>
</ns0:Messages>

Как я могу написать логику XSLT, чтобы генерировались следующие выходные данные?

    <?xml version="1.0" encoding="UTF-8"?>
<ns0:Messages xmlns:ns0="http://sap.com/xi/XI/SplitAndMerge">
    <ns0:Message1>
        <ns0:invoiceOrder xmlns:ns0="http://cts.com"
                   type="ABCD"
                   businessDivision="X0"
                   salesOrganization="XYZ10"
                   Channel="Y0">
            <ns0:references>
                <ns0:key type="Source System">ABC</ns0:key>
                <ns0:relationship scheme="Customer" schemeAgency="APAC" role="Sell to">703760000</ns0:relationship>
                <ns0:document type="Purchase Order">AB123</ns0:document>
            </ns0:references>
            <ns0:notes>
                <ns0:note type="XY67" language="EN">package1</ns0:note>
            </ns0:notes>
            <ns0:orderLines>
                <ns0:orderLine>
                    <ns0:identifiers>
                        <ns0:identifier scheme="Item" schemeAgency="ABC">100411</ns0:identifier>
                    </ns0:identifiers>
                    <ns0:amounts>
                        <ns0:amount type="credit Amount">274.50</ns0:amount>
                    </ns0:amounts>
                </ns0:orderLine>
                <ns0:orderLine>
                    <ns0:identifiers>
                        <ns0:identifier scheme="Item" schemeAgency="ABC">140072</ns0:identifier>
                    </ns0:identifiers>
                    <ns0:amounts>
                        <ns0:amount type="credit Amount">58.41</ns0:amount>
                    </ns0:amounts>
                </ns0:orderLine>
            </ns0:orderLines>
            <ns0:terms>
                <ns0:term type="Reason Code">D19</ns0:term>
                <ns0:term type="Payment Terms">Y000</ns0:term>
            </ns0:terms>
            <ns0:billingInfo>
                <ns0:paymentMethod/>
            </ns0:billingInfo>
            <ns0:flags>
                <ns0:flag type="1099 Payment Flag">Y</ns0:flag>
            </ns0:flags>
            <ns0:dates>
                <ns0:date type="Proposed Invoice Date">2018-11-02</ns0:date>
            </ns0:dates>
        </ns0:invoiceOrder>
        <ns0:invoiceOrder xmlns:ns0="http://cts.com"
                   type="ABCD"
                   businessDivision="X0"
                   salesOrganization="ABC10"
                   Channel="Y0">
            <ns0:references>
                <ns0:key type="Source System">ABC</ns0:key>
                <ns0:relationship scheme="Customer" schemeAgency="APAC" role="Sell to">702390000</ns0:relationship>
                <ns0:document type="Purchase Order">AB123</ns0:document>
            </ns0:references>
            <ns0:notes>
                <ns0:note type="XY34" language="EN">package2</ns0:note>
            </ns0:notes>
            <ns0:orderLines>
                <ns0:orderLine>
                    <ns0:identifiers>
                        <ns0:identifier scheme="Item" schemeAgency="ABC">100411</ns0:identifier>
                    </ns0:identifiers>
                    <ns0:amounts>
                        <ns0:amount type="Rebate Amount">76.25</ns0:amount>
                    </ns0:amounts>
                </ns0:orderLine>
                <ns0:orderLine>
                    <ns0:identifiers>
                        <ns0:identifier scheme="Item" schemeAgency="ABC">140072</ns0:identifier>
                    </ns0:identifiers>
                    <ns0:amounts>
                        <ns0:amount type="Rebate Amount">9.74</ns0:amount>
                    </ns0:amounts>
                </ns0:orderLine>
            </ns0:orderLines>
            <ns0:terms>
                <ns0:term type="Reason Code">Y19</ns0:term>
                <ns0:term type="Payment Terms">Y000</ns0:term>
            </ns0:terms>
            <ns0:billingInfo>
                <ns0:paymentMethod/>
            </ns0:billingInfo>
            <ns0:flags>
                <ns0:flag type="1099 Payment Flag">Y</ns0:flag>
            </ns0:flags>
            <ns0:dates>
                <ns0:date type="Proposed Invoice Date">2018-11-02</ns0:date>
            </ns0:dates>
        </ns0:invoiceOrder>
    </ns0:Message1>
</ns0:Messages>

Я пробовал много способов, но поскольку входные данные не являются правильно сформированными XML, у меня возникли проблемы с генерацией указанного выше вывода.

1 Ответ

0 голосов
/ 02 ноября 2018

Вы можете сделать это в XSLT 3, как это поддерживается Saxon 9.8 или 9.9 или Altova 2017/2018/2019, используя функцию XPath 3 parse-xml-fragment, например, вы можете передать фрагмент, который у вас есть, в качестве строкового параметра:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="#all"
    version="3.0">

    <xsl:param name="fragment-string" as="xs:string"><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
<ns0:invoiceOrder xmlns:ns0="http://cts.com"
               type="ABCD"
               businessDivision="X0"
               salesOrganization="XYZ10"
               Channel="Y0">
   <ns0:references>
      <ns0:key type="Source System">ABC</ns0:key>
      <ns0:relationship scheme="Customer" schemeAgency="APAC" role="Sell to">703760000</ns0:relationship>
      <ns0:document type="Purchase Order">AB123</ns0:document>
   </ns0:references>
   <ns0:notes>
      <ns0:note type="XY67" language="EN">package1</ns0:note>
   </ns0:notes>
   <ns0:orderLines>
      <ns0:orderLine>
         <ns0:identifiers>
            <ns0:identifier scheme="Item" schemeAgency="ABC">100411</ns0:identifier>
         </ns0:identifiers>
         <ns0:amounts>
            <ns0:amount type="credit Amount">274.50</ns0:amount>
         </ns0:amounts>
      </ns0:orderLine>
      <ns0:orderLine>
         <ns0:identifiers>
            <ns0:identifier scheme="Item" schemeAgency="ABC">140072</ns0:identifier>
         </ns0:identifiers>
         <ns0:amounts>
            <ns0:amount type="credit Amount">58.41</ns0:amount>
         </ns0:amounts>
      </ns0:orderLine>
   </ns0:orderLines>
   <ns0:terms>
      <ns0:term type="Reason Code">D19</ns0:term>
      <ns0:term type="Payment Terms">Y000</ns0:term>
   </ns0:terms>
   <ns0:billingInfo>
      <ns0:paymentMethod/>
   </ns0:billingInfo>
   <ns0:flags>
      <ns0:flag type="1099 Payment Flag">Y</ns0:flag>
   </ns0:flags>
   <ns0:dates>
      <ns0:date type="Proposed Invoice Date">2018-11-02</ns0:date>
   </ns0:dates>
</ns0:invoiceOrder>
<ns0:invoiceOrder xmlns:ns0="http://cts.com"
               type="ABCD"
               businessDivision="X0"
               salesOrganization="ABC10"
               Channel="Y0">
   <ns0:references>
      <ns0:key type="Source System">ABC</ns0:key>
      <ns0:relationship scheme="Customer" schemeAgency="APAC" role="Sell to">702390000</ns0:relationship>
      <ns0:document type="Purchase Order">AB123</ns0:document>
   </ns0:references>
   <ns0:notes>
      <ns0:note type="XY34" language="EN">package2</ns0:note>
   </ns0:notes>
   <ns0:orderLines>
      <ns0:orderLine>
         <ns0:identifiers>
            <ns0:identifier scheme="Item" schemeAgency="ABC">100411</ns0:identifier>
         </ns0:identifiers>
         <ns0:amounts>
            <ns0:amount type="Rebate Amount">76.25</ns0:amount>
         </ns0:amounts>
      </ns0:orderLine>
      <ns0:orderLine>
         <ns0:identifiers>
            <ns0:identifier scheme="Item" schemeAgency="ABC">140072</ns0:identifier>
         </ns0:identifiers>
         <ns0:amounts>
            <ns0:amount type="Rebate Amount">9.74</ns0:amount>
         </ns0:amounts>
      </ns0:orderLine>
   </ns0:orderLines>
   <ns0:terms>
      <ns0:term type="Reason Code">Y19</ns0:term>
      <ns0:term type="Payment Terms">Y000</ns0:term>
   </ns0:terms>
   <ns0:billingInfo>
      <ns0:paymentMethod/>
   </ns0:billingInfo>
   <ns0:flags>
      <ns0:flag type="1099 Payment Flag">Y</ns0:flag>
   </ns0:flags>
   <ns0:dates>
      <ns0:date type="Proposed Invoice Date">2018-11-02</ns0:date>
   </ns0:dates>
</ns0:invoiceOrder>]]></xsl:param>

    <xsl:output indent="yes"/>

    <xsl:template match="/" name="xsl:initial-template">
        <ns0:Messages xmlns:ns0="http://sap.com/xi/XI/SplitAndMerge">
            <ns0:Message1>
                <xsl:sequence select="parse-xml-fragment($fragment-string)"/>
            </ns0:Message1>
        </ns0:Messages>
    </xsl:template>

</xsl:stylesheet>

https://xsltfiddle.liberty -development.net / bFDb2Dd

Конечно, в XSLT 2/3 вы также можете загрузить другой документ с фрагментом, используя unparsed-text например,

<xsl:param name="fragment-uri" as="xs:string">fragment.xml</xsl:param>

<xsl:param name="fragment-string" as="xs:string" select="unparsed-text($fragment-uri)"/>

Пример на https://xsltfiddle.liberty -development.net / bFDb2Dd / 1 .

На уровне XML с поддерживаемыми внешними объектами вы можете использовать документ с требуемыми элементами-обертками, которые включают ваш фрагмент в качестве внешнего объекта, например, по адресу http://xsltransform.hikmatu.com/jyH9rLR или https://xsltfiddle.liberty -development.net / eiZQaGf , вы можете объявить документ-оболочку как

<!DOCTYPE ns0:Messages [
  <!ENTITY external-fragment SYSTEM "fragment.xml">
]>
<ns0:Messages xmlns:ns0="http://sap.com/xi/XI/SplitAndMerge">
    <ns0:Message1>&external-fragment;</ns0:Message1>
</ns0:Messages>
...