0
votes

I'm trying to render part of an Excel xml file as HTML for an improved preview when translating (foreign language translation) part of the content in a Computer Aided Translation tool.

I have this xml:

<?xml version="1.0" encoding="utf-8"?>
<?mso-application progid="Excel.Sheet"?>
<Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet"
 xmlns:o="urn:schemas-microsoft-com:office:office"
 xmlns:x="urn:schemas-microsoft-com:office:excel"
 xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"
 xmlns:html="http://www.w3.org/TR/REC-html40">
 <Styles>
  <Style ss:ID="Default">
   <Alignment ss:Vertical="Bottom"/>
  </Style>
  <Style ss:ID="Header">
   <Font ss:Bold="1"/>
  </Style>
  <Style ss:ID="DateFormat">
   <NumberFormat ss:Format="General Date"/>
  </Style>
 </Styles>
 <Worksheet ss:Name="ResultSet">
  <Table>
   <Row>
    <Cell><Data ss:Type="Number"><![CDATA[149768]]></Data></Cell>
    <Cell><Data ss:Type="String"><![CDATA["@" cannot be the first character in an e-mail address!]]></Data></Cell>
    <Cell><Data ss:Type="String"><![CDATA[Multiword - Noun]]></Data></Cell>
    <Cell><Data ss:Type="String"><![CDATA[]]></Data></Cell>
    <Cell><Data ss:Type="String"><![CDATA[]]></Data></Cell>
    <Cell><Data ss:Type="String"><![CDATA[Input validation message]]></Data></Cell>
    <Cell><Data ss:Type="String"><![CDATA[]]></Data></Cell>
   </Row>
  </Table>
 </Worksheet>
</Workbook>

I'm trying to take the second Data element from each Row and display it, but I cannot display this at all. I think it has something to do with the namespaces and I must be missing something, but can't see what. This is what I'm using:

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="urn:schemas-microsoft-com:office:spreadsheet" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet" xmlns:html="http://www.w3.org/TR/REC-html40">
 <xsl:template match="/">
  <html>
  <body>
    <xsl:for-each select="/Workbook/Worksheet/Table/Row"><br/>
      <font color="#380000" size="3"><xsl:value-of select="/Cell[2]/Data"/></font><br/>
    </xsl:for-each>
  </body>
  </html>
</xsl:template>
</xsl:stylesheet>

Can anyone help me with this?

I should add that I'm using Treebeard to test this and it validates the xml (which I have no control over) with these errors... adding to my confusion:

error: org.xml.sax.SAXParseException; lineNumber: 3; columnNumber: 10; Document is invalid: no grammar found. error: org.xml.sax.SAXParseException; lineNumber: 3; columnNumber: 10; Document root element "Workbook", must match DOCTYPE root "null".

Thank you

1
The error message suggests you XML document has <!DOCTYPE root> at the beginning but you have not shown anything like that at all. In any case, if you have a DOCTYPE, then the following name must match the root element name, i.e. if it is Workbook then the declaration needs to say <!DOCTYPE Workbook>. As for the namespace problem, that is the FAQ in relation to XSLT and XPath, see stackoverflow.com/questions/1730875/… for instance.Martin Honnen

1 Answers

1
votes

You have in fact two namespaces issues here:

  1. The output elements are in the default namespace, which you declared with xmlns="urn:schemas-microsoft-com:office:spreadsheet", but they should probably be in the XHTML namespace.
  2. Your XPath expressions select elements in the null namespace, but they should be selecting elements in the namespace urn:schemas-microsoft-com:office:spreadsheet. AFAIK, in XSLT 1.0 this can only be done using a prefix.

To solve problem 1., you can either change the default namespace declaration to xmlns="http://www.w3.org/1999/xhtml" or use a prefix for this namespace.

To solve problem 2., you have to prefix all element names in your XPath expressions with ss:, which is bound to the desired namesapce.

There is still another problem: The XPath expression /Cell[2]/Data starts with / and therefore is an absolute path expression. You want a relative one, so omit the slash.