Link to home
Start Free TrialLog in
Avatar of Molko
Molko

asked on

XSLT - XPath to the XSI definition attribute

I have some xml that I wish to transform, the transformation is dependant upon the

xsi:schemaLocation="http://example/prodv1.xsd http://example/otherstuff.xsd"
or
xsi:schemaLocation="http://example/otherstuff.xsd http://example/prodv2.xsd"

If its prov1 i want to do something, if its prodv2 i do something else. I guess they can come in any order as well

I can write the xpath to pick out all attributes (@*), but I can figure out a way to return a boolean (xpath) that evaulates the existance of http://example/prodv1.xsd



<?xml version="1.0" encoding="UTF-8"?>
<order xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://example/prodv1.xsd 
																																																		http://example/prodv2.xsd">
	<items>
		<product>
			<number xsi:type="xs:short">557</number>
			<name>Short-Sleeved Linen Blouse</name>
			<size xsi:nil="true"/>
		</product>
	</items>
</order>

Open in new window

Avatar of basicinstinct
basicinstinct
Flag of Australia image

not tested but wouldn't it be something like this?

/order[conatins(@xsi:schemaLocation, 'http://example/prodv1.xsd')]
Avatar of Molko
Molko

ASKER

Sorry, oops...a typo

I can write the xpath to pick out all attributes (@*), but I cant figure out a way to return a boolean (xpath) that evaulates the existance of http://example/prodv1.xsd
ASKER CERTIFIED SOLUTION
Avatar of Gertone (Geert Bormans)
Gertone (Geert Bormans)
Flag of Belgium image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
inside the predicate the expression renders to a boolean expression which is false if the returned nodeset is empty

You might be up to a somewhat bigger challenge

I guess they can come in any order as well

seems to imply that you are uncertain about the meaning of schemaLocation

schemaLocation has two components
the part before the space is the targetNamespace of the schema referenced, it is a URI, a resource identifier, which often takes the form of a URL, but it isn't one
the second part (after the white space) is the physical location of the schema, it is a URL and it should point to the actual schema.
Order in an @xsi:schemaLocation is important

For schema that don't have a target namespace there is
@xsi:noNamespaceSchemaLocation
It could be that you also have to test for that

Now the use of schemaLocation implies that the schema you are referring to has a targetNamespace. In that case, chances are that the XML elements defined in that schema are in that namespace. So most often you will find that attribute with an xmlns="..."
In that case the templates will not work, because you can't address the order element in the null namespace if it is in the schema target namespace

So you might have to make the XSLT namespace independent, using local-name(), like this

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     exclude-result-prefixes="xsi"
    version="1.0">
    <xsl:template match="/">
        <xsl:apply-templates select="/*"/>
    </xsl:template>
    
    <xsl:template match="/*[local-name() = 'order'][contains(@xsi:schemaLocation, 'http://example/prodv1.xsd')]">
        do one thing here
    </xsl:template>
    
    <xsl:template match="/*[local-name() = 'order'][not(contains(@xsi:schemaLocation, 'http://example/prodv1.xsd'))]">
        do other thing here
    </xsl:template>
    
</xsl:stylesheet>

Open in new window


In XSLT2 you can simply wildcard match="/*:order" but the above XSLT will work in both
Avatar of Molko

ASKER

Thankyou.