views:

42

answers:

2

I am trying to select all of the links in a xhtml document in xsl. Some of the anchor tags have the namespace declaration xmlns="http://www.w3.org/1999/xhtml" in them. These are not selected. e.g. with this xml doc:

<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="xsl.xsl"?>
<root>
<item>
this iz sum text and it haz sum <a xmlns="http://www.w3.org/1999/xhtml" href="http://cheezburger.com/"&gt;linx&lt;/a&gt; in it.
Teh linx haz piks of <a href="http://icanhascheezburger.com/"&gt;kittehs&lt;/a&gt; in dem.
</item>
</root>

and this xsl:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;
<xsl:template match="/">
<html xmlns="http://www.w3.org/1999/xhtml"&gt;
<dl>
<xsl:for-each select="//root/item/a">
    <dd><xsl:value-of select="."/></dd>
    <dt><xsl:value-of select="@href"/></dt>
</xsl:for-each>
</dl>
</html>
</xsl:template>
</xsl:stylesheet>

Only the second link is selected. Can someone explain what is going on here and how I might fix it?

+2  A: 

If you need both nodes, which are in different namespaces, use:

/root/item/*[local-name() = 'a']

However, this should seldomly happen, normally, you want a node from only one namespace:

<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:example="http://www.w3.org/1999/xhtml"
  >
....
<xsl:for-each select="/root/item/example:a">
Wrikken
this works - thanks you. the problem here is that not all of the links are marked with the name space.
Nick
Setting the default namespace to the correct one in the stylesheet tag (`xmlns="http://www.w3.org/1999/xhtml"`) should work to make `/root/item/a` select all items if the other 'anonymous' nodes should be in that namespace too.
Wrikken
@Wrikken: That last namespace declaration is usefull for output, not for select. XSLT 2.0 has a `xpath-default-namespace` attribute for that matter.
Alejandro
@Alejandro: Damn, you're right, I was not thinking straight. Good advice to the OP if all nodes should be in the same namespace is to follow your advice then :)
Wrikken
+1  A: 

The a elements are in 2 different namespaces, the default namespace and the xhtml namespace. If you move the XPath outside of the xhtml formatting, you can use both namespaces to search:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;

  <xsl:template match="/">
    <xsl:variable name="links" xmlns:xhtml="http://www.w3.org/1999/xhtml"
                  select="//root/item/(a | xhtml:a)"/>

    <html xmlns="http://www.w3.org/1999/xhtml"&gt;
      <dl>
        <xsl:for-each select="$links">
          <dd><xsl:value-of select="."/></dd>
          <dt><xsl:value-of select="@href"/></dt>
        </xsl:for-each>
      </dl>
    </html>
  </xsl:template>

</xsl:stylesheet>
Harold L