Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations gkittelson on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

quick xml namespace 1

Status
Not open for further replies.

MikeAJ

Programmer
May 22, 2002
108
US
I have an xml doc and an xsl doc. Recently, the service that provides that xml has added an xmlns to the rootnode, and now my xsl doesn't work. Here is an example of what's happening:

test.xml:
Code:
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="test.xsl"?>
<result>
   <person firstName="Mark" lastName="Smith"/>
   <person firstName="Jimmy" lastName="John"/>
</result>

test.xsl:
Code:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="[URL unfurl="true"]http://www.w3.org/1999/XSL/Transform"[/URL] targetNamespace="[URL unfurl="true"]http://localhost">[/URL]
   <xsl:template match="/">
      <html>
         <body>
            <table border="0" cellspacing="0" cellpadding="5">
               <xsl:for-each select="/result/person">
                  <tr>
                     <td valign="top"><xsl:value-of select="position()"/>.</td>
                     <td valign="top"><xsl:value-of select="@firstName"/></td>
                     <td valign="top"><xsl:value-of select="@lastName"/></td>
                  </tr>
               </xsl:for-each>
            </table>
         </body>
      </html>
   </xsl:template>
</xsl:stylesheet>
Which works fine, but when the xml contains a namespace the xsl does nothing:
Code:
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="test.xsl"?>
<result xmlns="[URL unfurl="true"]http://localhost">[/URL]
   <person firstName="Mark" lastName="Smith"/>
   <person firstName="Jimmy" lastName="John"/>
</result>

What do I need to add to my xsl to read this namespace?

Thanks!
 
Code:
<xsl:stylesheet version="1.0" xmlns:xsl="[URL unfurl="true"]http://www.w3.org/1999/XSL/Transform"[/URL]  xmlns="[URL unfurl="true"]http://localhost"[/URL] targetNamespace="[URL unfurl="true"]http://localhost">[/URL]

Your last xml document uses a default namespace, therefore each element is by default qualified by that namespace. Since your XSL does not specify a default namespace, unqualified element names (among other things) remain unqualified, and therefore do not match.

Tom Morrison
 
I feel obliged to offer different sort of advice.

[1] targetNamespace is not in the xsl:stylesheet element's attribute list. It should be taken out.

[2] To match elements with default namespace in place, you still need to use qualified name. However, the prefix is something not canonical. It can be arbitary.
[tt]
<?xml version="1.0" encoding="UTF-8"?>
<!-- [1] targetNamespace taken out; [2] Q is arbitrary -->
<xsl:stylesheet version="1.0" xmlns:xsl=" [blue]xmlns:Q="[/blue]>
<xsl:template match="/">
<html>
<body>
<table border="0" cellspacing="0" cellpadding="5">
<xsl:for-each select="/[blue]Q:[/blue]result/[blue]Q:[/blue]person">
<tr>
<td valign="top"><xsl:value-of select="position()"/>.</td>
<td valign="top"><xsl:value-of select="@firstName"/></td>
<td valign="top"><xsl:value-of select="@lastName"/></td>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
[/tt]
 
Thanks Tom, but I'm still not getting anything.

When I save this to test.xml:
Code:
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="test.xsl"?>
<result xmlns="[URL unfurl="true"]http://localhost">[/URL]
   <person firstName="Mark" lastName="Smith"/>
   <person firstName="Jimmy" lastName="John"/>
</result>


and this to test.xsl:
Code:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="[URL unfurl="true"]http://www.w3.org/1999/XSL/Transform"[/URL] xmlns="[URL unfurl="true"]http://localhost">[/URL]
   <xsl:template match="/">
      <html>
         <body>
            <table border="0" cellspacing="0" cellpadding="5">
               <xsl:for-each select="/result/person">
                  <tr>
                     <td valign="top"><xsl:value-of select="position()"/>.</td>
                     <td valign="top"><xsl:value-of select="@firstName"/></td>
                     <td valign="top"><xsl:value-of select="@lastName"/></td>
                  </tr>
               </xsl:for-each>
            </table>
         </body>
      </html>
   </xsl:template>
</xsl:stylesheet>

and then try to view text.xml in Firefox or IE, I get a blank screen. However, if I remove the namespace from the xml, it works fine.

Any Ideas?

Thanks Again!
 
oops, I didn't refresh the page, tsuji, so I didn't see your reply. I tried what you said and it worked. Is there anyway to define the prefix globally so that I don't have to use "Q:" before each node?

Thanks!
 
>Is there anyway to define the prefix globally so that I don't have to use "Q:" before each node?
If it is posed in full generality, I don't know and I doubt there is one.
Nevertheless, for restricted cases where the risk of namespace mixed-up is null, use local-name() everywhere in predicate for matching, then you can even suppress the reference to the default namespace in the xsl:stylesheet element and the whole xsl is processed based on the local-name everywhere.
[tt]
<xsl:for-each [blue]select="/*[local-name='result']/*[local-name()='person']"[/blue]>
<tr>
<td valign="top"><xsl:value-of select="position()"/>.</td>
<td valign="top"><xsl:value-of select="@firstName"/></td>
<td valign="top"><xsl:value-of select="@lastName"/></td>
</tr>
</xsl:for-each>
[/tt]
 
Amendment
I missed one pair of () in typing up. The corresponding line should be read like this.

[tt] <xsl:for-each [blue]select="/*[local-name[/blue][red]()[/red][blue]='result']/*[local-name()='person']"[/blue]>[/tt]

 
Cool, didn't know about local-name(), but it's useful. Thanks again for all your help!
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top