Search code examples
xmlxsltmaximo

Is there a way to set condition in XSL action: "AddChange"?


Is there a way to set condition in XSL action: "AddChange" if the condition is within its child tag? Im quite new here in XSL transformation. What I am trying to do here is, if the STATUS is "WAPPR", the action must be "Add" otherwise "AddChange" will be used.

Here's the xml:

<?xml version="1.0" encoding="UTF-8"?>
<SyncS1MXWO xmlns="http://www.ibm.com/maximo" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" creationDateTime="2021-07-02T09:45:55+08:00" transLanguage="EN" baseLanguage="EN" messageID="2048616251903490366380">
  <S1MXWOSet>
    <WORKORDER action="AddChange">
      <STATUS>WAPPR</STATUS>
    </WORKORDER>
  </S1MXWOSet>
</SyncS1MXWO>

Here's my XLS:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:max="http://www.ibm.com/maximo"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:java="http://xml.apache.org/xslt/java" 
version="1.0"
exclude-result-prefixes="xsd xsi max java">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

<xsl:template match="max:WORKORDER">
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:max="http://www.ibm.com/maximo">
   <soapenv:Header/>
   <soapenv:Body>
      <max:SyncMXWO>
         <max:MXWOSet>
            <WORKORDER action="AddChange">
               <STATUS><xsl:value-of select="max:STATUS"/></STATUS>
               <xsl:variable name="STATUS" select="max:STATUS"/>
               <xsl:if test="$STATUS = 'WAPPR'">
                  <xsl:attribute name="action">Add</xsl:attribute>
               </xsl:if>
            </WORKORDER>
         </max:MXWOSet>
      </max:SyncMXWO>
   </soapenv:Body>
</soapenv:Envelope>
</xsl:template>
</xsl:stylesheet>

Here's my expected output:

    <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
   <soapenv:Header/>
   <soapenv:Body>
      <max:SyncMXWO xmlns:max="http://www.ibm.com/maximo">
         <max:MXWOSet>
            <WORKORDER action="Add">
               <STATUS>WAPPR</STATUS>
            </WORKORDER>
         </max:MXWOSet>
      </max:SyncMXWO>
   </soapenv:Body>
</soapenv:Envelope>

Here's the error im getting: Error executing XSLT at line 20 : An attribute node (action) cannot be created after a child of the containing element. Most recent element start tag was output at line 18 of module


Solution

  • --- edited in response to clarification ---

    You are getting an error because you are attempting to add an attribute to an element after children have been added to it; that is not allowed. Try instead:

    <xsl:template match="max:WORKORDER">
        <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:max="http://www.ibm.com/maximo">
        <soapenv:Header/>
            <soapenv:Body>
                <max:SyncMXWO>
                    <max:MXWOSet>
                        <WORKORDER action="AddChange">
                            <xsl:if test="max:STATUS= 'WAPPR'">
                                <xsl:attribute name="action">Add</xsl:attribute>
                            </xsl:if>
                            <STATUS>
                                <xsl:value-of select="max:STATUS"/>
                            </STATUS>
                        </WORKORDER>
                    </max:MXWOSet>
                </max:SyncMXWO>
            </soapenv:Body>
        </soapenv:Envelope>
    </xsl:template>
    

    Not sure why you need the $STATUS variable if you're not using it consistently. Either get rid of the variable altogether as shown above or do:

                    <WORKORDER action="AddChange">
                        <xsl:variable name="STATUS" select="max:STATUS"/>
                        <xsl:if test="$STATUS= 'WAPPR'">
                            <xsl:attribute name="action">Add</xsl:attribute>
                        </xsl:if>
                        <STATUS>
                            <xsl:value-of select="$STATUS"/>
                        </STATUS>
                    </WORKORDER>