XSL Transform, select on prefix namespace?

I am trying to select a node from the following xml that have prefix from namespace:

<gesmes:Envelope xmlns:gesmes="http://www.gesmes.org/xml/2002-08-01">
<Cube>
    <Cube time="2009-10-12">
        <Cube currency="USD" rate="1.4765"/>
        .............................

the xsl I am using is (Updated): The original xml is at: http://www.ecb.europa.eu/stats/eurofxref/eurofxref-hist-90d.xml

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:gesmes="http://www.gesmes.org/xml/2002-08-01" xmlns="http://www.ecb.int/vocabulary/2002-08-01/eurofxref"  xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="/"> 
    <xdoc>
        <ccurency>
        <xsl:for-each select="gesmes:Envelope/Cube/Cube">
<xsl:variable name="atime" select="@time"/>  
        <xsl:for-each select="Cube">
                <row>
                <xsl:element name="Date">
                <xsl:value-of select="$atime"/>
                </xsl:element>    
                        <xsl:element name="Currency">
                <xsl:value-of select="@currency"/>
                </xsl:element>
                <xsl:element name="Rate">
                <xsl:value-of select="@rate"/>
                </xsl:element>
        </row>
        </xsl:for-each>
    </xsl:for-each>
    </ccurency>         
</xdoc>                 
</xsl:template>
</xsl:stylesheet>

This is not working, the select is empty. If I change the gesmes:Envelope to simple Envelope both at xml and xsl everything works fine?

How can I select it with prefix ?

13.10.2009 17:45:26
2 ОТВЕТА
РЕШЕНИЕ

It seems that you are looking for something like this:

<xsl:stylesheet 
  version="1.0" 
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:gesmes="http://www.gesmes.org/xml/2002-08-01" 
  xmlns:exr="http://www.ecb.int/vocabulary/2002-08-01/eurofxref"
  exclude-result-prefixes="gesmes exr"
>
  <xsl:output method="xml" indent="yes" encoding="utf-8" />

  <xsl:template match="gesmes:Envelope">
    <xdoc>
      <ccurency>
        <xsl:apply-templates select="exr:Cube/exr:Cube/exr:Cube" />
      </ccurency>
    </xdoc>
  </xsl:template>

  <xsl:template match="exr:Cube[@currency and @rate]">
    <row>
      <Date>
        <xsl:value-of select="../@time" />
      </Date>
      <Currency>
        <xsl:value-of select="@currency" />
      </Currency>
      <Rate>
        <xsl:value-of select="@rate" />
      </Rate>
    </row>
  </xsl:template>

</xsl:stylesheet>

When applied to your input XML, it produces:

<xdoc>
  <ccurency>
    <row>
      <Date>2009-07-16</Date>
      <Currency>PHP</Currency>
      <Rate>67.739</Rate>
    </row>
    <row>
      <Date>2009-07-16</Date>
      <Currency>SGD</Currency>
      <Rate>2.0501</Rate>
    </row>
    <row>
      <Date>2009-07-16</Date>
      <Currency>THB</Currency>
      <Rate>48.13</Rate>
    </row>
    <row>
      <Date>2009-07-16</Date>
      <Currency>ZAR</Currency>
      <Rate>11.4575</Rate>
    </row>
  </ccurency>
</xdoc>

Notes:

  • Don't use <xsl:for-each> whenever possible. It looks more familiar and less frightening than <xsl:apply-templates>, but it is not the best option most of the time.
  • You don't need to build elements with <xsl:element>, you can write them directly.
  • You don't need to store a variable with that @time value you are interested in. You can always refer to the parent node and pull it from there directly (../@time)
  • I used exclude-result-prefixes to make namespaces disappear from the output entirely, you seem to want to get rid of them
2
14.10.2009 10:02:02

Make sure that you've declared the namespace in the root element of the transform:

<xsl:stylesheet xmlns:gesmes="http://www.gesmes.org/xml/2002-08-01" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

Looking at your logic and input XML, it looks like the inner for-each will never select nodes, since the context is changed to the inner <cube> element, namespace or no. That could just be a result of shortening your XML for the question, though...

3
13.10.2009 18:02:20
Thanks, I post my comments as new answer due to character limit.
Nikos K. 14.10.2009 08:36:55