1

I'm transforming XML to XML using the following XSLT. I need to validate the source XML for required element. If the sibling node's value is missing for the required node then create a new node. Here is the XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="/">
        <Data Schema="XML A">
            <xsl:apply-templates/>
        </Data>
    </xsl:template>
    <xsl:template match="Attribute[not(Type=following::Type)]">
        <Attributes type="{Type}">
            <xsl:apply-templates 
                 select="../Attribute[Type=current()/Type]" mode="out"/>
        </Attributes>
    </xsl:template>
    <xsl:template match="Attribute" mode="out">
        <Attr id="{id}" name="{Name}" value="{Value}"/>
    </xsl:template>
    <xsl:template match="Attribute"/>
</xsl:stylesheet>

Here is the XML

<?xml version="1.0" encoding="windows-1252"?>
<XML>
    <Attributes>
        <Attribute>
            <id>331</id>
            <Name>Enviornment</Name>
            <Type>common</Type>
            <Value>Development</Value>
        </Attribute>
        <Attribute>
            <id>79</id>
            <Name>Retail</Name>
            <Type>common</Type>
            <Value></Value>
        </Attribute>
        <Attribute>
            <id>402</id>
            <Name>Gender</Name>
            <Type>category</Type>
            <Value>Men</Value>
        </Attribute>
    </Attributes>
</XML>

And if the required elements is missing then it should create the following XML. I have multiple required elements.

<?xml version="1.0" encoding="utf-8"?>
<Data Schema="XML A">
  <Attributes type="common">
    <Attr id="331" name="Enviornment" value="Development" />
    <Attr id="79" name="Retail" value="" />
  </Attributes>
  <Attributes type="category">
    <Attr id="402" name="Gender" value="Men" />
  </Attributes>
  <errorCodes>
    <errorCode>"value for Retail is missing."</errorCode>
  </errorCodes>
</Data>

And if it can be done using the following XSLT then it will be a big plus. Thanks in Advance.

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:key name="type" match="Attribute" use="Type"/>
    <xsl:template match="/">
        <Data Schema="XML A">
            <xsl:apply-templates select="XML/Attributes/Attribute">
                 <xsl:sort select="Type" order="descending"/>
            </xsl:apply-templates>
        </Data>
    </xsl:template>
    <xsl:template 
            match="Attribute[generate-id()=generate-id(key('type', Type)[1])]">
        <Attributes type="{Type}">
            <xsl:apply-templates 
                    select="../Attribute[Type=current()/Type]" mode="out"/>
        </Attributes>
    </xsl:template>
    <xsl:template match="Attribute" mode="out">
         <Attr id="{id}" name="{Name}" value="{Value}"/>
    </xsl:template>
    <xsl:template match="Attribute"/>
</xsl:stylesheet>

1 Answer 1

6

The following stylesheet:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:key name="type" match="Attribute" use="Type"/>
    <xsl:template match="/">
        <Data Schema="XML A">
            <xsl:apply-templates select="XML/Attributes/Attribute">
                 <xsl:sort select="Type" order="descending"/>
            </xsl:apply-templates>
            <errorCodes>
                <xsl:apply-templates select="XML/Attributes/Attribute" 
                                     mode="errors"/>
            </errorCodes>
        </Data>
    </xsl:template>
    <xsl:template 
            match="Attribute[generate-id()=generate-id(key('type', Type)[1])]">
        <Attributes type="{Type}">
            <xsl:apply-templates 
                    select="../Attribute[Type=current()/Type]" mode="out"/>
        </Attributes>
    </xsl:template>
    <xsl:template match="Attribute" mode="out">
         <Attr id="{id}" name="{Name}" value="{Value}"/>
    </xsl:template>
    <xsl:template match="Attribute"/>
    <xsl:template match="Attribute" mode="errors"/>
    <xsl:template match="Attribute[Value='']" mode="errors">
        <errorCode>"value for <xsl:value-of select="Name"/> is missing."</errorCode>
    </xsl:template>
</xsl:stylesheet>

Produces the desired output:

<Data Schema="XML A">
    <Attributes type="common">
        <Attr id="331" name="Enviornment" value="Development" />
        <Attr id="79" name="Retail" value="" />
    </Attributes>
    <Attributes type="category">
        <Attr id="402" name="Gender" value="Men" />
    </Attributes>
    <errorCodes>
        <errorCode>"value for Retail is missing."</errorCode>
    </errorCodes>
</Data>
Sign up to request clarification or add additional context in comments.

3 Comments

I have 1 more question. I have to check for a specific Attributes/Attribute/Type=ComplexAttr. If it is present in the source then I have to create <Attr> inside <Attribute type="common"> else I have to default it to some values. Can you guide me on how to achieve this output.
1 more thing the above XSLT is checking all of them. However, I want to validate only specific ones which are required. For example, When node is /Attributes/Attribute/Name=Retail then check the value of /Attributes/Attribute/Value and if it is missing then create an <error> node
@JohnXsl - you should upvote Iwburk for this excellent work. I did.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.