简体   繁体   中英

XSLT help - transform attributes to elements and rename elements

I'm an XSLT newbie and am trying to transform the following XML to the next XML. I've commented significant changes needed in the second XML.

There are 2 major changes:

1) Since node2 element name repeats, I want to rename the second occurrence. 2) I want itemName attributes to each become an Element. 2a) For the [Customer ID] itemValue, I'll need it to be renamed 'CustomerID' when transformed to an Element.

In summary, I want the original to be transformed to a more table-like, columnar structure after being rendered in the browser.

<requestStatus>
<node1>
    <clientId>4634</clientId>
    <affiliateId>0</affiliateId>
    <contactId>144756</contactId>
    <requestId>64086</requestId>
    <transNumber>F27A6A65</transNumber>
    <status>11</status>
    <paymentType>D</paymentType>
    <amount>1.99</amount>
    <contactEmail>fmaraicar@linked2pay.com</contactEmail>
    <templateName>Payment Form 2</templateName>
    <createdBy>0</createdBy>
    <paymentCnt>1</paymentCnt>
    <nextPaymtDate/>
    <recurringFrequency/>
    <maxPayments>0</maxPayments>
    <untilDate/>
    <node2>
        <node2>
            <paymtId>56991</paymtId>
            <paidAmount>1.99</paidAmount>
            <paymentMethod>C</paymentMethod>
            <paymentSeq>1</paymentSeq>
            <submissionDate>08/04/2016</submissionDate>
            <creditCardType>V</creditCardType>
            <creditCardNumber>1111</creditCardNumber>
            <cardHolder>Ronald McDonald</cardHolder>
            <expirationMonth>1</expirationMonth>
            <expirationYear>2017</expirationYear>
            <achRequestId>0</achRequestId>
            <accountNumber/>
            <accountType/>
            <depositType/>
            <achSubmissionDate/>
            <achEffectiveDate/>
        </node2>
    </node2>
    <node3>
        <node4>
            <itemName>[FirstName]</itemName>
            <itemValue>Ronald</itemValue>
        </node4>
        <node4>
            <itemName>[LastName]</itemName>
            <itemValue>McDonald</itemValue>
        </node4>
        <node4>
            <itemName>[Email]</itemName>
            <itemValue>fmaraicar@linked2pay.com</itemValue>
        </node4>
        <node4>
            <itemName>[Amount]</itemName>
            <itemValue>1.99</itemValue>
        </node4>
        <node4>
            <itemName>Customer ID</itemName>
            <itemValue>CUSTOMER1</itemValue>
        </node4>
        <node4>
            <itemName>Invoice Numbers</itemName>
            <itemValue>INV10001,INV10002</itemValue>
        </node4>
    </node3>
</node1>
</requestStatus>


    To this:

<requestStatus>
<node1>
    <clientId>4634</clientId>
    <affiliateId>0</affiliateId>
    <contactId>144756</contactId>
    <requestId>64086</requestId>
    <transNumber>F27A6A65</transNumber>
    <status>11</status>
    <paymentType>D</paymentType>
    <amount>1.99</amount>
    <contactEmail>fMcDonald@somewhere.com</contactEmail>
    <templateName>Payment Form 2</templateName>
    <createdBy>0</createdBy>
    <paymentCnt>1</paymentCnt>
    <nextPaymtDate/>
    <recurringFrequency/>
    <maxPayments>0</maxPayments>
    <untilDate/>
    <node2>
        <node2b>   <!-- since node2 element was repeated, rename this as node2b -->
            <paymtId>56991</paymtId>
            <paidAmount>1.99</paidAmount>
            <paymentMethod>C</paymentMethod>
            <paymentSeq>1</paymentSeq>
            <submissionDate>08/04/2016</submissionDate>
            <creditCardType>V</creditCardType>
            <creditCardNumber>1111</creditCardNumber>
            <cardHolder>Ronald McDonald</cardHolder>
            <expirationMonth>1</expirationMonth>
            <expirationYear>2017</expirationYear>
            <achRequestId>0</achRequestId>
            <accountNumber/>
            <accountType/>
            <depositType/>
            <achSubmissionDate/>
            <achEffectiveDate/>
        </node2b>   
    </node2>
    <node3>  
        <FirstName>Ronald</FirstName>  <!-- each itemName attribute to become a unique Element -->
        <LastName>McDonald</LastName>
        <Email>fMcDonald@somewhere.com</Email>
        <Amount>1.99</Amount>
        <CustomerID>CUSTOMER1</CustomerID>  
        <InvoiceNumbers>INV10001,INV10002</InvoiceNumbers>
    </node3>
</node1>

I am not entirely sure of your precise requirements, but in situations like this where you are only transforming a portion of the XML, it is usually best to start with the identity transform

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

Then, you only need to write templates for the nodes you wish to transform. So, for example, to rename the node2 to node2b you would do this...

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

The node2/node2 match ensures only the child node2 is matched, not the parent. Replace these with your actual element names, of course.

For the node4 elements, you can use the xsl:element element, together with Attribute Value Templates to create new elements, based on another value

  <xsl:element name="{translate(itemName, '[] ', '')}">
      <xsl:value-of select="itemValue" />
  </xsl:element>

The translate function here will strip out the specified symbols from the name. Do not that itemName is an element, not an attribute.

Try this XSLT as starters:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output method="xml" indent="yes" />

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

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

    <xsl:template match="node4">
        <xsl:element name="{translate(itemName, '[] ', '')}">
            <xsl:value-of select="itemValue" />
        </xsl:element>
    </xsl:template>
</xsl:stylesheet>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM