如何从带名称空间的XML中“选择”?

时间:2008-11-12 14:27:36

标签: xml xslt

我有一个类似:::

的XML文档
<?xml version="1.0" encoding="utf-8"?>
<?mso-application progid="Excel.Sheet"?>
<Workbook xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"
          xmlns:o="urn:schemas-microsoft-com:office:office"
          xmlns:x="urn:schemas-microsoft-com:office:excel"
          xmlns="urn:schemas-microsoft-com:office:spreadsheet">
  <Worksheet ss:Name="Worksheet1">
    <Table>
      <Column ss:Width="100"></Column>

      <Row>
        <Cell ss:Index="1" ss:StyleID="headerStyle">
          <Data ss:Type="String">Submitted By</Data>
        </Cell>
      </Row>
      <Row>
        <Cell ss:Index="1" ss:StyleID="alternatingItemStyle">
          <Data ss:Type="String">Value1-0</Data>
        </Cell>
      </Row>
    </Table>
    <AutoFilter xmlns="urn:schemas-microsoft-com:office:excel"
                x:Range="R1C1:R1C5"></AutoFilter>
  </Worksheet>
</Workbook>

问题在于尝试使用

选择行
  <xsl:for-each select="//Row">
    <xsl:copy-of select="."/>
  </xsl:for-each>

不匹配。我删除了所有的名称间距,它工作正常。那么,我如何让'select'匹配Row?

3 个答案:

答案 0 :(得分:30)

在XSLT中声明名称空间的名称空间前缀,然后使用该前缀声明select

<xsl:stylesheet ... xmlns:os="urn:schemas-microsoft-com:office:spreadsheet">
  ...   
  <xsl:for-each select="//os:Row">
    ...
  </xsl:for-each>
  ...
</xsl:stylesheet>

这通常会导致XPath易于阅读。但是,XSLT / XPath工具生成以下等效代码:

<xsl:for-each select="//*[local-name()='Row' = and namespace-uri()='urn:schemas-microsoft-com:office:spreadsheet']">
   ...
</xsl:for-each>

答案 1 :(得分:10)

如果您不关心命名空间,可以使用XPath`local-name()'函数:

<xsl:for-each select="//*[local-name() = 'Row']">
  <xsl:copy-of select="."/>
</xsl:for-each>

或者,同样的事情可以这样表达。我不确定这是否是标准XPath,如果所有XPath实现都支持它(ColdFusion确实如此,那么Java也可以这样做)。也许有人知道这是否符合任何标准。

<xsl:for-each select="//:Row">
  <xsl:copy-of select="."/>
</xsl:for-each>

答案 2 :(得分:7)

Tomalekckarras提供了很好的答案,但我想澄清其背后的原因。

您不匹配的元素位于文档中它们出现的作用域的默认名称空间中,也就是说,它们位于为该作用域声明的名称空间中没有前缀(例如。

xmlns="urn:schemas-microsoft-com:office:spreadsheet"
<{1>}元素上的

。即使标记名缺少名称空间前缀,它们也在名称空间中。

但是,XPath要求命名空间中的所有元素名称都使用前缀限定,或者在谓词中使用Workbook显式指定名称空间。因此,您必须在谓词中使用namespace-uri()函数来匹配元素名称(如果跨命名空间存在名称冲突的危险,也必须使用local-name()函数),或者必须声明每个您希望在XPath中使用前缀匹配元素的名称空间,并在XPath表达式中使用其名称空间前缀限定元素名称。