15

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?

3 Answers 3

37

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>
Sign up to request clarification or add additional context in comments.

Comments

11

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>

8 Comments

This QName test *:local-name is valid only in XSLT/XPath 2.0
This solution is a little dirty, but effective. It solved my problem too (of trying to select a slippery namespaced child node).
@Kevin Which part of it? First or second?
Absolutely. Especially if namespace URIs are not fixed. If you only have a few possible URIs you can also register all of them and write <xsl:for-each select="ns1:foo|ns2:foo|ns3:foo">.
Well, that's a default namespace declaration. The notion of default namespaces for XPath does not exist in XSLT 1.0. Just register xmlns:xhtml="http://www.w3.org/1999/xhtml" in your XSLT file and use the prefix like select="xhtml:body".
|
7

Tomalek and ckarras give good answers, but I want to clarify the reasons behind them.

The elements you aren't matching are in the default namespace of the scope in which they occur in the doc, that is, they are in the namespace declared for that scope without a prefix (e.g.

xmlns="urn:schemas-microsoft-com:office:spreadsheet"

on the Workbook element). Even though the tagnames lack a namespace prefix, they are in a namespace.

However, XPath requires that all names of elements in a namespace be qualified with a prefix, or that the namespace be specified explicitly with namespace-uri() in a predicate. Hence, you must either use the local-name() function in a predicate to match the element name (and use the namespace-uri() function as well if there is a danger of name collisions across namespaces), or you must declare each namespace in which you wish to match elements in XPaths with a prefix, and qualify the element names with their namespace prefixes in the XPath expressions.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.