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

Gre*_*gle 13 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>
Run Code Online (Sandbox Code Playgroud)

问题是尝试选择Rows时

  <xsl:for-each select="//Row">
    <xsl:copy-of select="."/>
  </xsl:for-each>
Run Code Online (Sandbox Code Playgroud)

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

cka*_*ras 32

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

<xsl:stylesheet ... xmlns:os="urn:schemas-microsoft-com:office:spreadsheet">
  ...   
  <xsl:for-each select="//os:Row">
    ...
  </xsl:for-each>
  ...
</xsl:stylesheet>
Run Code Online (Sandbox Code Playgroud)

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

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

  • 后者似乎更简洁.谢谢. (2认同)

Tom*_*lak 10

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

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

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

<xsl:for-each select="//:Row">
  <xsl:copy-of select="."/>
</xsl:for-each>
Run Code Online (Sandbox Code Playgroud)


Chu*_*ckB 7

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

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

xmlns="urn:schemas-microsoft-com:office:spreadsheet"
Run Code Online (Sandbox Code Playgroud)

Workbook元素上).即使标记名缺少名称空间前缀,它们也位于名称空间中.

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