Replacing the element tag with value to end tag

2019-08-12 09:38发布

问题:

I have this requirement: I need to get the value of an element from the XML and conditionally populate it with an empty element. The only thing that comes to mind is to use the XSLT.

Condition: If PaymentMethodCode is equal to NONE, or does not exist, I need to populate this empty element: <eb:NoPayment/>

For example:

INPUT FILE:

<Invoice xmlns="http://schema.infor.com/InforOAGIS/2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://schema.infor.com/InforOAGIS/2 http://schema.infor.com/2.12.x/InforOAGIS/BODs/SyncInvoice.xsd" Language="ger" DocumentTitle="Invoice">
     <Country CountryCode="AT">Austria</Country>
     <PaymentMethodCode>NONE</PaymentMethodCode>
</Invoice>

My expected output should be:

<eb:Invoice xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.ebinterface.at/schema/4p1/ http://www.ebinterface.at/schema/4p1/" xmlns:eb="http://www.ebinterface.at/schema/4p1/" eb:Language="ger" eb:DocumentTitle="Invoice">>
     <eb:Country eb:CountryCode="AT">Austria</eb:Country>
     <eb:PaymentMethod>
          <eb:NoPayment/>
     </eb:PaymentMethod>
</eb:Invoice>

Is this possible? I don't have any idea how to actually do that in the XSLT.

回答1:

An XSLT 1.0 solution:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:infor="http://schema.infor.com/InforOAGIS/2" 
    xmlns:eb="http://www.ebinterface.at/schema/4p1/" 
    exclude-result-prefixes="infor" 
    version="1.0">

    <xsl:template match="@* | node()">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="infor:Invoice" priority="1">
        <eb:Invoice>
            <!--handle any existing child content-->
            <xsl:apply-templates select="@* | node()"/>

            <xsl:if test="not(infor:PaymentMethodCode)">
                <!--create eb:PaymentMethodCode/eb:NoPayment-->
                <xsl:call-template name="PaymentMethodCode"/> 
            </xsl:if>
        </eb:Invoice>
    </xsl:template>

    <!--If there is not text node, or if the value is 'NONE', 
        create an empty NoPayment element-->
    <xsl:template match="infor:PaymentMethodCode[not(text()) or .='NONE']" 
                  name="PaymentMethodCode" priority="1">
        <eb:PaymentMethodCode>
          <eb:NoPayment/>
        </eb:PaymentMethodCode>
    </xsl:template>

    <!--Change the namespace for InforOAGIS elements -->
    <xsl:template match="*[namespace-uri()='http://schema.infor.com/InforOAGIS/2']">
        <xsl:element name="eb:{local-name()}">
            <xsl:apply-templates select="@*|node()"/>
        </xsl:element>
    </xsl:template>

    <!--Change the namespace of attributes from InforOAGIS elements -->
    <xsl:template match="*[namespace-uri()='http://schema.infor.com/InforOAGIS/2']/@*">
      <xsl:attribute name="eb:{local-name()}">
          <xsl:value-of select="."/>
      </xsl:attribute>
    </xsl:template>

</xsl:stylesheet>


回答2:

I just did the following XSLT:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:infor="http://schema.infor.com/InforOAGIS/2" xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="xs" version="2.0">

    <xsl:template match="/">
        <xsl:apply-templates select="*"/>
    </xsl:template>

    <xsl:template match="infor:Invoice">
        <xsl:copy>
            <xsl:choose>
                <xsl:when test="not(exists(infor:PaymentMethodCode))">
                    <xsl:element name="PaymentMethodCode" namespace="http://schema.infor.com/InforOAGIS/2">
                        <xsl:element name="NoPayment" namespace="http://schema.infor.com/InforOAGIS/2"/>
                    </xsl:element>
                </xsl:when>                
            </xsl:choose>
            <xsl:apply-templates select="*|text()|@*"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="infor:PaymentMethodCode">
        <xsl:copy>
            <xsl:choose>
                <xsl:when test="text()='NONE'">
                    <xsl:element name="NoPayment" namespace="http://schema.infor.com/InforOAGIS/2"/>
                </xsl:when>
                <xsl:when test="not(text())">
                    <xsl:element name="NoPayment" namespace="http://schema.infor.com/InforOAGIS/2"/>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:apply-templates select="*|text()|@*"/>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="*|text()|@*">
        <xsl:copy>
            <xsl:apply-templates select="*|text()|@*"/>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

This will create the NoPayment element if there is no PaymentMethodCode given or it contains the value "NONE".

Input:

<Invoice xmlns="http://schema.infor.com/InforOAGIS/2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://schema.infor.com/InforOAGIS/2 http://schema.infor.com/2.12.x/InforOAGIS/BODs/SyncInvoice.xsd">
    <PaymentMethodCode></PaymentMethodCode>
    <PaymentMethodCode>NONE</PaymentMethodCode>
    <PaymentMethodCode>something elese</PaymentMethodCode>
</Invoice>

Gives the output:

<?xml version="1.0" encoding="UTF-8"?>
<Invoice xmlns="http://schema.infor.com/InforOAGIS/2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://schema.infor.com/InforOAGIS/2 http://schema.infor.com/2.12.x/InforOAGIS/BODs/SyncInvoice.xsd">
    <PaymentMethodCode><NoPayment/></PaymentMethodCode>
    <PaymentMethodCode><NoPayment/></PaymentMethodCode>
    <PaymentMethodCode>something elese</PaymentMethodCode>
</Invoice>


标签: xml xslt