Link to home
Start Free TrialLog in
Avatar of cookiejar
cookiejarFlag for United States of America

asked on

XML Namespace with XPATH

After adding namespaces to my xml document, my xsl doc no longer return results. Could you please tell me what I am doing wrong?  I am a student and is not familiar with this technology.

I have set up a default and prefixed namespace.  I don't know how to reference these in the xsl file.  I am not sure if I have set the namespaces up correctly .

 See my attachments.
contacts-2.xml
contacts.xsl
Avatar of Gertone (Geert Bormans)
Gertone (Geert Bormans)
Flag of Belgium image

Hi,
This is an issue that hits every XSLT developer at least once :-)

In your XML you are using a default namespace
    xmlns="http://www.nathan.com/ns/family"
    xmlns:fr="http://www.nathan.com/ns/friend"

But usually in your XSLT the default namespace is used for the output tree
so the default namespace is taken
so you need to add a prefix for the default namespace from the source doc as well
    xmlns:fam="http://www.nathan.com/ns/family"
    xmlns:fr="http://www.nathan.com/ns/friend"
in your stylesheet element

and then use the prefixes in the XPaths
<xsl:stylesheet version="1.0"
    xmlns:fam="http://www.nathan.com/ns/family"
    xmlns:fr="http://www.nathan.com/ns/friend"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="/">
    <!-- 
		 Name: Marilyn Nathan
		 Date: 24 Feb 2015
		 Course#:  CIS 205
		 Assignment#:  Module 2 Project 2
	 
	 -->
  <html>
  
    <head>
      <title>My Contacts</title>
    </head>
	
    <body>
      <h1>My Contacts</h1>
	  
	  <h2>Family</h2>
	  
      <table border="1" style="width:90%">
      <tbody>
      
          <tr bgcolor="#FAFAFA">
              <th style="text-align:center">Name</th>
              <th style="text-align:center">Address</th>			  
              <th style="text-align:center">City</th>
			  <th style="text-align:center">State</th>
              <th style="text-align:center">Zip Code</th>
			  <th style="text-align:center">Phone</th>			  
              <th style="text-align:center">Birthday</th>	
              <th style="text-align:center">Favorite Color</th>		  
		  </tr>
		  
        <xsl:for-each select="//fam:family">
		<xsl:sort select="fam:name"/>
            <tr>
                <td><xsl:apply-templates select="fam:name"/></td>
                <td><xsl:apply-templates select="fam:address"/></td>
                <td><xsl:apply-templates select="fam:city"/></td>
                <td><xsl:apply-templates select="fam:state"/></td>
                <td align="right"><xsl:apply-templates select="fam:zip_code"/></td>
                <td align="right"><xsl:apply-templates select="fam:phone"/></td>
                <td align="right"><xsl:apply-templates select="fam:birthday"/></td>	
			 <td><xsl:apply-templates select="@favcolor"/></td>	
            </tr>
         </xsl:for-each>
      </tbody>	  
      </table>
	  
	  <h2>Friends</h2>
	  
	  <table border="1" style="width:90%" >
      <tbody>
      
          <tr bgcolor="#FAFAFA">
              <th style="text-align:center">Name</th>
              <th style="text-align:center">Address</th>			  
              <th style="text-align:center">City</th>
			  <th style="text-align:center">State</th>
              <th style="text-align:center">Zip Code</th>
			  <th style="text-align:center">Phone</th>			  
              <th style="text-align:center">Birthday</th>
              <th style="text-align:center">Favorite Color</th>			  
		  </tr>
		  
        <xsl:for-each select="//fr:friend">
		<xsl:sort select="name"/>
            <tr>
                <td><xsl:apply-templates select="fr:name"/></td>
                <td><xsl:apply-templates select="fr:address"/></td>
                <td><xsl:apply-templates select="fr:city"/></td>
                <td><xsl:apply-templates select="fr:state"/></td>
                <td align="right"><xsl:apply-templates select="fr:zip_code"/></td>
                <td align="right"><xsl:apply-templates select="fr:phone"/></td>
                <td align="right"><xsl:apply-templates select="fr:birthday"/></td>
			 <td><xsl:apply-templates select="@favcolor"/></td>		
            </tr>
         </xsl:for-each>
      </tbody>	  
      </table>
      </body>
    </html>
</xsl:template>

</xsl:stylesheet>

Open in new window

above XSLT has fixed the issue

Let me make one comment.
It is good that you experiment with namespaces.
But namespaces are used to avoid name clashes for things that have the same name but a different meaning
or to group things that belong together

In your XML you have made fam:name and fr:name two different things
That actually is a poor use of namespaces, because regardless the fact that they are naming either a friend or a family.... it is the name of a person. In my XML I would definitely make sure that fam:name and fr:name were the same thing

I know you are just experimenting likely, and you are learning
but please take that lesson for granted
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
Avatar of cookiejar

ASKER

If I change to the following:

<contacts
             xmlns:fam="http://www.nathan.com/ns/family"
             xmlns:fr="http://www.nathan.com/ns/friend"
             xmlns:per="http://www.nathan.com/ns/person"
             
       >
Do I still use fam: and fr: as the prefixes at the parent level in the XSL doc?  <xsl:for-each select="//fam:family"> and <xsl:for-each select="//fr:family">
Do I prefix the children with per?  <td><xsl:apply-templates select="per:name"/></td>
<td><xsl:apply-templates select="per:address"/></td>

Also, in what cases would one use namespace?

Thanks  you for your excellent help.
Yes, that is how to do that
you need to know that you define an element in a namespace
by saying "this element is part of that namespace"
You can do so by having a default namespace or by adding a prefix (and a prefix binding)
What the prefix is does not matter, the namespace uri it is bound to is important

<fam:family xmlns:fam="http://www.nathan.com/ns/family"/>
and
<foo:family xmlns:foo="http://www.nathan.com/ns/family"/>
though the prefix is different, the elements are associated to the same namespace

you use namespaces as I said earlier to:
namespaces are used to avoid name clashes for things that have the same name but a different meaning
 or to group things that belong together