Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to 'select' from XML with namespaces?

Tags:

xml

xslt

I have an XML document something like :::

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

The problem is when trying to select Rows with

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

It is not matching. I removed all of the name-spacing and it works fine. So, how do I get the 'select' to match Row?

like image 260
oglester Avatar asked Nov 12 '08 14:11

oglester


2 Answers

Declare a namespace prefix for the namespace in your XSLT and then select using that prefix:

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

This usually results in XPaths that are easy to read. However, XSLT/XPath tools generate the following, equivalent code:

<xsl:for-each select="//*[local-name()='Row' = and namespace-uri()='urn:schemas-microsoft-com:office:spreadsheet']">
   ...
</xsl:for-each>
like image 138
ckarras Avatar answered Oct 25 '22 15:10

ckarras


If you don't care about the namespace, you can use the XPath `local-name()' function:

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

Alternatively the same same thing can be expressed like this. I'm not certain if this is standard XPath and if all XPath implementations support it (ColdFusion does, so probably Java does as well). Maybe someone knows if this conforms to any standard.

<xsl:for-each select="//:Row">
  <xsl:copy-of select="."/>
</xsl:for-each>
like image 45
Tomalak Avatar answered Oct 25 '22 17:10

Tomalak