我有一个类似:::
的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?
答案 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)
Tomalek和ckarras提供了很好的答案,但我想澄清其背后的原因。
您不匹配的元素位于文档中它们出现的作用域的默认名称空间中,也就是说,它们位于为该作用域声明的名称空间中没有前缀(例如。
xmlns="urn:schemas-microsoft-com:office:spreadsheet"
<{1>}元素上的。即使标记名缺少名称空间前缀,它们也在名称空间中。
但是,XPath要求命名空间中的所有元素名称都使用前缀限定,或者在谓词中使用Workbook
显式指定名称空间。因此,您必须在谓词中使用namespace-uri()
函数来匹配元素名称(如果跨命名空间存在名称冲突的危险,也必须使用local-name()
函数),或者必须声明每个您希望在XPath中使用前缀匹配元素的名称空间,并在XPath表达式中使用其名称空间前缀限定元素名称。