XSL转换,选择前缀命名空间?

时间:2009-10-13 17:45:26

标签: xml xslt namespaces

我正在尝试从以下xml中选择一个具有命名空间前缀的节点:

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

我正在使用的xsl是(更新的): 原始xml位于: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>

这不起作用,选择为空。如果我改变gesmes:信封到xml和xsl的简单信封一切正常吗?

如何选择前缀?

2 个答案:

答案 0 :(得分:3)

确保您已在变换的根元素中声明了命名空间:

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

查看您的逻辑和输入XML,看起来内部for-each永远不会选择节点,因为上下文被更改为内部<cube>元素,名称空间或否。这可能只是缩短你的问题的XML的结果,但是......

答案 1 :(得分:2)

看来你正在寻找这样的东西:

<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>

当应用于输入XML时,它会生成:

<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>

注意:

  • 尽可能不要使用<xsl:for-each>。它看起来比<xsl:apply-templates>更熟悉,更不可怕,但大多数时候它并不是最佳选择。
  • 您不需要使用<xsl:element>构建元素,您可以直接编写它们。
  • 您不需要存储您感兴趣的@time值的变量。您可以随时引用父节点并直接从中拉出它(../@time
  • 我使用exclude-result-prefixes使命名空间完全从输出中消失,你似乎想要摆脱它们