XML to XML using XSLT: How to check that element exists in output xml and if not create element with default value

1.6k Views Asked by At

Newbie here with XSLT. I'm creating one XML from another XML. Each XML follows different XSDs but are very similiar. I've been giving a list of required elements that are to be present in final output xml. So I have the xpath of all the required elements. My question is how do I ensure that the required elements exist, and if not I'm to generate the required elements in output xml file.

So my approach: being that source XML and output XML (target XML) will be very similar with little differences (XSDs are 90% same) I am first copying over entire xml with identity transformation template. Then I need to do some checking for the required elements to ensure they are present within the result tree.

For example:

Given this XML:

<?xml version="1.0" encoding="UTF-8"?>
<orders>
    <order>
        <order_id>555435699</order_id>
        <products>
            <product>Book1</product>
            <product>Book2</product>
        </products>
        <customer>
            <name>Mike Smith</name>
            <address>1222 N 1st St, Chicago IL</address>
        </customer>
    </order>
</orders>

OUTPUT should be something like:

<?xml version="1.0" encoding="UTF-8"?>
<orders>
    <order>
        <order_id>555435699</order_id>
        <products>
            <product>Book1</product>
            <product>Book2</product>
        </products>
        <customer>
            <name>Mike Smith</name>
            <address>1222 N 1st St, Chicago IL</address>
                     <phone>555-555-5555</phone> <!-- Required element 'phone' needs to be populated with default value in output if it doesn't exist -->
        </customer>
    </order>
</orders>

Need to be sure customer phone data exists or needs to be created with default value of '555-555-5555

<xsl:if test="not(node_xpath)">
    <!-- need to add the element -->
</xsl:if>

How do we do check in xslt using such as "if" and "test". I've seen these used here and there. Do these go in a separate templates of their own, or do they need to be included. How is this supposed to be applied for above example?

UPDATE:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:output method="xml" indent="yes"/>

<!-- copy entire xml from source xml file -->
<xsl:template match="@*|node()">
   <xsl:copy>
      <xsl:apply-templates select="@*|node()" />
   </xsl:copy>   
</xsl:template>

<!-- need to check for required tags -  - HOW TO INTEGRATE THIS PART -->
<xsl:if test="not(orders/order/customer/phone)">
    <phone>555-555-5555</phone>
</xsl:if>
</xsl:stylesheet>
2

There are 2 best solutions below

2
On BEST ANSWER

Just add a template matching an order with no customer, and have it write the default customer to the result:

XSLT 1.0

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

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

<xsl:template match="order[not(customer)]">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
        <customer>
            <phone>555-555-5555</phone>
        </customer>
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>

I think I wasn't too clear in beginning. Let's say I need to be sure each customer has a <phone> element data. If not then I need to populate this in xml outpu with default value.

Then match a customer with no phone instead:

<xsl:template match="customer[not(phone)]">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
        <phone>555-555-5555</phone>
    </xsl:copy>
</xsl:template>
1
On

I would create a template for each of the required output nodes. You want the template to match if there's not an existing input node to copy from. You can insert the default results for the missing data into the template.

xsl is rather complex but very powerful. You'll need to read the documentation to understand it.