Reputation: 2515
I am trying to debug an issue related to xpath. I created a variable $MetaData in my XSLT assigning a xml document but for some reason, foreach loop didn't able to locate its child and I couldn't able to get inside foreach loop.
XSLT:
<!-- language: lang-xslt -->
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet
version="1.0"
xmlns="http://www.w3.org/TR/xhtml1/strict"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt">
<xsl:variable name="_MetaData">
<MetaData>
<EmployeeId>1233</EmployeeId>
<EmployeeName>abcd</EmployeeName>
</MetaData>
</xsl:variable>
<xsl:variable name="MetaData" select="msxsl:node-set($_MetaData)"></xsl:variable>
<xsl:template match="*|@*">
<xsl:copy>
<xsl:copy-of select="@*" />
<xsl:apply-templates />
</xsl:copy>
</xsl:template>
<xsl:template match="*[local-name()='MetaDataTag']">
<xsl:copy>
<MetaData VocabularyOwner="acme.com" Vocabulary="MetaData">
<xsl:for-each select="$MetaData//MetaData/*">
<xsl:element name="Occurrence">
<xsl:attribute name="Id">
<xsl:value-of select="local-name(.)"/>
</xsl:attribute>
<xsl:attribute name="Value">
<xsl:value-of select="string(.)"/>
</xsl:attribute>
</xsl:element>
</xsl:for-each>
</MetaData>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
XML:
<?xml version="1.0" encoding="utf-8" ?>
<Envelope>
<MetaDataTag />
</Envelope>
If I remove xmlns xmlns="http://www.w3.org/TR/xhtml1/strict" namespace, everything seems working fine and I am able to get inside the loop. I am not sure how can I resolve this issue without removing xmlns="http://www.w3.org/TR/xhtml1/strict" namespace.
Upvotes: 0
Views: 664
Reputation: 19482
If you define the default namespace in the XSLT the nodes in your variable will be in that namespace. Xpath does not have a default namespace so $MetaData//MetaData/*
will not match the {http://www.w3.org/TR/xhtml1/strict}MetaData
element node.
One solution is to ignore the namespaces using local-name()
.
`$MetaData//*[local-name() = 'MetaData']/*`
Or you can define an (additional) prefix for your Xpath expressions...
<xsl:stylesheet
version="1.0"
xmlns="http://www.w3.org/TR/xhtml1/strict"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xhtml="http://www.w3.org/TR/xhtml1/strict">
...
</xsl:stylesheet>
... and use it in the expression.
`$MetaData//xhtml:MetaData/*`
But the tags are not valid in the XHTML namespace so it would be a better idea create the data elements in the empty namespace:
<xsl:variable name="_MetaData">
<MetaData xmlns="">
<EmployeeId>1233</EmployeeId>
<EmployeeName>abcd</EmployeeName>
</MetaData>
</xsl:variable>
<xsl:variable name="MetaData" select="msxsl:node-set($_MetaData)"/>
Or you define a specific namespace for them...
<xsl:stylesheet
version="1.0"
xmlns="http://www.w3.org/TR/xhtml1/strict"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:data="urn:data">
<xsl:variable name="_MetaData">
<data:MetaData>
<data:EmployeeId>1233</data:EmployeeId>
<data:EmployeeName>abcd</data:EmployeeName>
</data:MetaData>
</xsl:variable>
<xsl:variable name="MetaData" select="msxsl:node-set($_MetaData)"/>
...
</xsl:stylesheet>
to use in the expression:
$MetaData//data:MetaData/*
Upvotes: 1