amitz27
amitz27

Reputation: 69

Ignoring XML namespace prefix while selecting elements - XSLT

XML Version 1

<inboundData xmlns="urn:college:names:ws:docexchange">
<Root>
        <College Version="5.0" xmlns:cidx="urn:abc:names:specification:col:schema:all:5:0" xmlns="urn:abc:names:specification:col:schema:all:5:0">
           <Header>
              <Address>
                 <AddressLine1>4600 Big Tree Way</AddressLine1>
              </Address>
           </Header>
    </College>
</Root>
</inboundData>

XML Version 2

<inboundData xmlns="urn:college:names:ws:docexchange">
<Root>
        <ns1:College Version="5.0" xmlns:ns1="urn:abc:names:specification:col:schema:all:5:0">
           <ns1:Header>
              <ns1:Address>
                 <ns1:AddressLine1>4600 Big Tree Way</ns1:AddressLine1>
              </ns1:Address>
           </ns1:Header>
    </ns1:College>
</Root>
</inboundData>

XSL Code

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:a="urn:abc:names:specification:col:schema:all:5:0" xmlns:b="urn:college:names:ws:docexchange">
<xsl:template match="/">
    <xsl:copy-of select="b:inboundData/b:College/*"/>
</xsl:template>
</xsl:stylesheet>

Correction in the XSL code. (Realized the error after reading Hansen's response)

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:a="urn:abc:names:specification:col:schema:all:5:0" xmlns:b="urn:college:names:ws:docexchange">
<xsl:template match="/">
    <xsl:copy-of select="b:inboundData/b:Root/*"/>
</xsl:template>
</xsl:stylesheet>

The XSL code works well for XML version 1. Due to the extra namespace "ns1", it does not work for type 2. How can I make the xsl code work for both these versions? Kindly enlighten me!

Upvotes: 1

Views: 11796

Answers (2)

Thomas W
Thomas W

Reputation: 15391

You can match elements by their local name, like

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:a="urn:abc:names:specification:col:schema:all:5:0" 
    xmlns:b="urn:college:names:ws:docexchange">
  <xsl:template match="/">
    <xsl:copy-of select="b:inboundData/*[local-name()='College']/*"/>
  </xsl:template>
</xsl:stylesheet>

Upvotes: 6

Mads Hansen
Mads Hansen

Reputation: 66796

The College element is bound to the same namespace for both documents.

Whether or not the XML documents use a namespace-prefix or if they have different prefix values is irrelevant. They are "seen" by the XML processor as the same type of element and are addressed the same way through XPath, since they are bound to the same namespace.

The namespace-prefix used in an XPath statement does not have to match the namespace-prefix in the XML document (as it would be impossible to predict what namesapce-prefixes someone might choose to use). However, the namespace that it is bound to must match.

Both of your XML documents are equivalent. Whether or not the elements have a namaspece-prefix, the elements are bound to the same namespaces.

If you look at how they are declared and what they map to, in the first XML document:

<College Version="5.0" 
 xmlns:cidx="urn:abc:names:specification:col:schema:all:5:0"
 xmlns="urn:abc:names:specification:col:schema:all:5:0">

declares an element named College without a namespace-prefix that is bound to the namespace urn:abc:names:specification:col:schema:all:5:0 because of the declaration of the namespace without a namespace-prefix xmlns="urn:abc:names:specification:col:schema:all:5:0".

In the second example:

<ns1:College Version="5.0" 
     xmlns:ns1="urn:abc:names:specification:col:schema:all:5:0">

Declares an element named College using a namespace-prefix which is bound to the namespace urn:abc:names:specification:col:schema:all:5:0.

The descendant elements of those College elements in both examples are bound to the same namespace as the College element that defined what the namespace for the ns1 namespace-prefix in the first example, or the null namespace-prefix in the second example document.

Any XSLT and XPath addressing those elements should return the same results.

Your template match in your XSLT should not work for either documents, as College is not a child of inboundData.

You would either need to adjust it to:

b:inboundData/b:Root/a:College/*

or

b:inboundData//a:College/*

Upvotes: 4

Related Questions