0

I have XML in the following format:

     <?xml version="1.0"?>
<MES_VEHICLE_STATUS_DESCRIPTOR xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="MOM.Production"  PRODUCTIONORDER="000001995795" >
  <POSECTION LOCATION="" />
  <ORDERSECTION SALESORDER=""  />
  <MATERIALCONSUMPTIONSECTION>
    <MATERIAL_CONSUMPTION DESC="car" QTY="1.000" WORKPLACE="3001_GAT101LH">BIN1000004</MATERIAL_CONSUMPTION>
    <MATERIAL_CONSUMPTION DESC="PLAIN_WASHER" QTY="1.000" WORKPLACE="3001_GAT101LH">WRE20000018</MATERIAL_CONSUMPTION>
    <MATERIAL_CONSUMPTION DESC="car" QTY="1.000" WORKPLACE="3001_GAT101LH">BIN1000003</MATERIAL_CONSUMPTION>
    
  </MATERIALCONSUMPTIONSECTION>
</MES_VEHICLE_STATUS_DESCRIPTOR>

and output should look like that:

    <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
                  xmlns:mat="http://mes.com/ScrapManagement">
   <soapenv:Header/>
   <soapenv:Body>
      <mat:DT_SCRAPMANAGEMENT_MES_REQ>
         <DATA>
            <PlantCode>3002</PlantCode>
            <SAPOrder>000001995795</SAPOrder>
            <Quantity>1.000</Quantity>
            <PartNo>BIN1000004</PartNo>
            <WorkPlace>3001_GAT101LH</WorkPlace>
         </DATA>
         <DATA>
            <PlantCode>3002</PlantCode>
            <SAPOrder>000001995795</SAPOrder>
            <Quantity>1.000</Quantity>
            <PartNo>WRE20000018</PartNo>
            <WorkPlace>3001_GAT101LH</WorkPlace>
         </DATA>
         <DATA>
            <PlantCode>3002</PlantCode>
            <SAPOrder>000001995795</SAPOrder>
            <Quantity>1.000</Quantity>
            <PartNo>BIN1000003</PartNo>
            <WorkPlace>3001_GAT101LH</WorkPlace>
         </DATA>
                     
      </mat:DT_SCRAPMANAGEMENT_MES_REQ>
   </soapenv:Body>
</soapenv:Envelope>

My XSLT to transform

    <xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    >
    <xsl:output encoding="UTF-8" indent="yes" method="xml" version="1.0" />
    <xsl:template match="MES_VEHICLE_STATUS_DESCRIPTOR">
        <soapenv:Envelope
            xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
            xmlns:mat="http://mes.com/ScrapManagement">
            <soapenv:Header />
            <soapenv:Body>
                <xsl:element name="mat:DT_SCRAPMANAGEMENT_MES_REQ">
                    <xsl:variable name="po" select="@PRODUCTIONORDER" />
                    <xsl:for-each select="MATERIALCONSUMPTIONSECTION/MATERIAL_CONSUMPTION">
                        <DATA>
                            <PlantCode>
                                <xsl:text>3002</xsl:text>
                            </PlantCode>
                            <SAPOrder>
                                <xsl:value-of select="$po" />
                            </SAPOrder>
                            <Quantity>
                                <xsl:value-of select="@QTY" />
                            </Quantity>
                            <PartNo>
                                <xsl:value-of select="." />
                            </PartNo>
                            <WorkPlace>
                                <xsl:value-of select="@WORKPLACE" />
                            </WorkPlace>
                        </DATA>
                    </xsl:for-each>
                </xsl:element>
            </soapenv:Body>
        </soapenv:Envelope>
    </xsl:template>
</xsl:stylesheet>

If i delete xmlns="MOM.Production" in XML file, the transformation is OK. But if have it in xml file, cannot transform. I use website: https://www.online-toolz.com/tools/xslt-transformation.php and show the error: Error:DOMDocument::loadXML(): xmlns: URI MOM.Production is not absolute in Entity, line: 2. I don't understand what is reason. I don't understand what is reason

  • Please do not add problems to the question after it has been answered. The solution to your new issue can be found here: https://stackoverflow.com/a/34762628/3016153. – michael.hor257k Apr 14 '21 at 09:31

1 Answers1

1

The code you had in mind is probably more or less this:

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

  <xsl:template match="MES_VEHICLE_STATUS_DESCRIPTOR">
    <xsl:for-each select="MATERIALCONSUMPTIONSECTION/MATERIAL_CONSUMPTION">
      <xsl:element name="DATA">
        <xsl:element name="PRODUCTIONORDER">
          <xsl:value-of select="../../@PRODUCTIONORDER" />
        </xsl:element>
        <xsl:element name="QTY">
          <xsl:value-of select="@QTY" />
        </xsl:element>
        <xsl:element name="MATERIAL">
          <xsl:value-of select="text()" />
        </xsl:element>
      </xsl:element>
    </xsl:for-each>
  </xsl:template>

</xsl:stylesheet>

I think you have to understand the difference between relative and absolute paths in the XPATH expressions your are using to select the correct nodes.

When you are inside a template matching the node MES_VEHICLE_STATUS_DESCRIPTOR, you don't use absolute paths like /MATERIALCONSUMPTIONSECTION/MATERIAL_CONSUMPTION (which doesn't exist in this case), but paths relative to this node, as MATERIALCONSUMPTIONSECTION/MATERIAL_CONSUMPTION.

When you are inside a <xsl:for-each select="MATERIALCONSUMPTIONSECTION/MATERIAL_CONSUMPTION"> loop, you have to select the nodes with relative paths like text(), ../../@PRODUCTIONORDER or @QTY. Notice the @ telling the QTY and PRODUCTIONORDER are attribute type nodes.

Finally, your current output is no well formed XML since it lacks a root element.

Personnaly, I would replace the <xsl:element> tag by its litteral value and avoid the computation of a constant field accross a loop:

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

  <xsl:template match="MES_VEHICLE_STATUS_DESCRIPTOR">
    <xsl:variable name="po" select="@PRODUCTIONORDER" />
    <xsl:for-each select="MATERIALCONSUMPTIONSECTION/MATERIAL_CONSUMPTION">
      <DATA>
        <PRODUCTIONORDER><xsl:value-of select="$po" /></PRODUCTIONORDER>
        <QTY><xsl:value-of select="@QTY" /></QTY>
        <MATERIAL><xsl:value-of select="." /></MATERIAL>
      </DATA>
    </xsl:for-each>
  </xsl:template>

</xsl:stylesheet>
Pierre François
  • 5,850
  • 1
  • 17
  • 38