Tomislav Vuletic
Tomislav Vuletic

Reputation: 11

XML element name has empty space, how to address it in XSLT?

I started learning Linux couple of days ago and currently I'm stuck at XSLT. Sorry if it's a stupid question or already answered elsewhere, I'm quite new here.

My XML looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<lac xmlns:t="http://smth.de">
    <header>
        <order id="20210323346730329408"/>
        <adress id="IZ0009"/>
    </header>
        <items>
            <item id="1"><material><code>IS-0001-BT-1</code><lotcode/></material><qty>10,000000</qty><expiry/></item>
            <item id="2"><material><code>IS-0001-BT-2</code><lotcode/></material><qty>20,000000</qty><expiry/></item>
            <item id="3"><material><code>IS-0001-AZ-1</code><lotcode/></material><qty>30,000000</qty><expiry/></item>
            <item id="4"><material><code>IS-0001-AZ-2</code><lotcode/></material><qty>40,000000</qty><expiry/></item>
        </items>
</lac>

I want to get this output:

Order ID,Adress ID,Item ID,MaterialCode,MaterialLotCode,MaterialQty,Expiry
20210323346730329408,IZ0009,1,IS-0001-BT-1,,10,000000,
20210323346730329408,IZ0009,2,IS-0001-BT-2,,20,000000,
20210323346730329408,IZ0009,3,IS-0001-AZ-1,,30,000000,
20210323346730329408,IZ0009,4,IS-0001-AZ-2,,40,000000,

This is what I got sofar, Your help is very welcome:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" encoding="UTF-8"/>
<xsl:strip-space elements="*" />

<xsl:template match="/">
<xsl:text>Order ID,Adress ID,Item ID,MaterialCode,MaterialLotCode,MaterialQty,Expiry&#x0A;</xsl:text> 
<xsl:apply-templates mode="runHeader"/>
 <xsl:apply-templates mode="runItems"/>
</xsl:template>

<xsl:template match="header" mode="runHeader">
 <xsl:apply-templates mode="runOrder"/>
 <xsl:apply-templates mode="runAdress"/>
</xsl:template>

<xsl:template match="order" mode="runOrder">
<xsl:value-of select="./@id"/>
<xsl:text>,</xsl:text>
</xsl:template>

<xsl:template match="adress" mode="runAdress">
<xsl:value-of select="./@id"/>
<xsl:text>,</xsl:text>
</xsl:template>

<xsl:template match="items" mode="runItems">
    <xsl:for-each select="//item">
    <xsl:value-of select="./@id"/>
    <xsl:text>,</xsl:text>
    <xsl:value-of select="./material"/>
    <xsl:text>,</xsl:text>
    <xsl:value-of select="./lotcode"/>
    <xsl:text>,</xsl:text>
    <xsl:value-of select="./qty"/>
    <xsl:text>,</xsl:text>
    <xsl:value-of select="./expiry"/>
    <xsl:text>&#x0A;</xsl:text>
</xsl:for-each>
</xsl:template>

</xsl:stylesheet>

Many thanks in advance.

Upvotes: 1

Views: 85

Answers (1)

michael.hor257k
michael.hor257k

Reputation: 117100

I would suggest a different approach:

XSLT 1.0

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

<xsl:template match="/lac">
    <!-- header row -->
    <xsl:text>Order ID,Adress ID,Item ID,MaterialCode,MaterialLotCode,MaterialQty,Expiry&#10;</xsl:text> 
    <!-- common data -->
    <xsl:variable name="common">
        <xsl:value-of select="header/order/@id"/>
        <xsl:text>,</xsl:text>
        <xsl:value-of select="header/adress/@id"/>
        <xsl:text>,</xsl:text>
    </xsl:variable>
    <!-- data rows -->
    <xsl:for-each select="items/item">
        <xsl:copy-of select="$common"/>
        <xsl:value-of select="@id"/>
        <xsl:text>,</xsl:text>
        <xsl:value-of select="material/code"/>
        <xsl:text>,</xsl:text>
        <xsl:value-of select="material/lotcode"/>
        <xsl:text>,</xsl:text>
        <xsl:value-of select="qty"/>
        <xsl:text>,</xsl:text>
        <xsl:value-of select="expiry"/>
        <xsl:text>&#10;</xsl:text>
    </xsl:for-each>
</xsl:template>

</xsl:stylesheet>

Note that this assumes that each item has at most one material (your XML structure allows for more).

--
P.S. That's not how you spell address.

Upvotes: 1

Related Questions