Recursive AI

Office 2003 XML (WordprocessingML 2003, SpreadsheetML 2003)

All onedocument docs

Both formats are read-only. A file opens as a Document or a Workbook by conversion: the reader turns the 2003 file into an in-memory OOXML package (DOCX or XLSX) on the markup layer and the hub wraps that package like any other. What the hub then holds saves as DOCX or XLSX, extracts as text and converts as any OOXML file does. Document.ImportLoss and Workbook.ImportLoss list what did not map (null for a file that was opened natively). Writing the 2003 formats is not supported.

C#
using Document doc = Document.Open("old.xml");       // sniffed: Word 2003 XML
using Workbook wb = Workbook.Open("old.xml");        // sniffed: Excel 2003 XML
Office.Convert("old.xml", "new.docx");               // or .xlsx
LossReport? lost = doc.ImportLoss;

The static entry points are WordMl2003.ToPackage/Open (RecursiveAI.OneDocument.Documents.Xml2003) and SpreadsheetMl2003.ToPackage/Open (RecursiveAI.OneDocument.Spreadsheets.Xml2003); they take an IByteSource, an OpenContext and an optional ILossSink.

Identification

By content, never the extension (FormatSniffer): the mso-application processing instruction (Word.Document, Excel.Sheet) or the root namespace (http://schemas.microsoft.com/office/word/2003/wordml, urn:schemas-microsoft-com:office:spreadsheet), ahead of generic XML. The files are .xml (Word's "Word 2003 XML Document", Excel's "XML Spreadsheet 2003") and sometimes .doc or .xls by name.

Reading rules

  • The file is parsed once with the markup tokenizer (no System.Xml). DTDs and entity declarations are refused; nesting, attribute counts and part size obey OfficeLimits. Not well-formed XML is xml.*; a root that is not the format's is wml2003.not-wordml or sml2003.not-spreadsheet. Everything else is repaired and reported (defects.md); the reader raises nothing but OfficeException.
  • Order in the output follows the ECMA-376 schema sequences, not the order in the 2003 file: property lists (paragraph, run, table, row, cell, section, style, list level) are read into a set and written in schema order. A property that appears twice keeps its last occurrence.
  • Hyperlink targets become external relationships. Nothing is fetched, linked pictures are not followed, and data in w:binData is decoded but never executed.
  • Names carry hyphens in 2003 (w:first-line, w:h-ansi, w:line-rule) and camel case in 2006. Attribute and element names convert by that rule, with w:fareast → eastAsia. Hyphenated enumeration values (dash-long, next-page, at-least) convert the same way. Fractional measures (LibreOffice writes 4320.5401) round to whole numbers; empty attributes are left out.

Word

2003Becomes
o:DocumentPropertiesdocProps/core.xml (title, subject, author, keywords, description, last author, revision, created, saved, category) and docProps/app.xml (company, manager, pages, words, characters, lines, paragraphs, characters with spaces, total time)
o:CustomDocumentPropertiesdocProps/custom.xml (dt:dt string, boolean, integer, float)
w:fonts/w:defaultFontsw:docDefaults/w:rPrDefault/w:rFonts
w:styles/w:styleword/styles.xml; wx:uiName is a hint and ignored (w:name is kept); latent styles are dropped
w:lists (w:listDef, w:list)word/numbering.xml (w:abstractNum, w:num, level overrides); w:nfc codes map to number formats; w:listPr in a paragraph becomes w:numPr
w:docPrword/settings.xml: zoom, track revisions, default tab stop, character spacing control; even-page headers set w:evenAndOddHeaders
wx:sect, wx:sub-sectionread through; a section's w:sectPr goes on the last paragraph before it, the last section's closes the body
w:hdr, w:ftr (in w:sectPr)word/headerN.xml, word/footerN.xml with odd → default, even, first
w:p, w:r, w:t, w:tab, w:br, w:sym, …the same elements; a run nested in a run (LibreOffice inside a hyperlink) becomes a sibling
w:tbltables with grid, w:hmerge → w:gridSpan, w:vmerge → w:vMerge; a missing grid is made from the widest row; a cell always ends with a paragraph
w:fldSimple, w:fldCharunchanged
w:hlinkw:hyperlink (w:dest → relationship, w:bookmark → w:anchor)
aml:annotation bookmark start/endw:bookmarkStart/End
aml:annotation Word.Comment*word/comments.xml, w:commentRangeStart/End, w:commentReference
aml:annotation Word.Insertion, Word.Deletionw:ins, w:del (text becomes w:delText) with author and date
w:footnote, w:endnote (inline in a run)word/footnotes.xml, word/endnotes.xml with separators, and the reference
w:pict with v:imagedata and w:binDataa DrawingML inline picture (word/media/imageN.*; the type is taken from the bytes, the size from the VML style)
w:pict with v:textboxa VML text box with converted content
w:smartTag, w:customXml, w:sdtremoved, text kept

Dropped, with loss.* codes: loss.unmapped-markup.<element> (any element without a counterpart, one line per element name), loss.shapes (VML shapes with neither picture nor text), loss.pictures, loss.ole-objects (reduced to the preview picture), loss.smart-tags, loss.custom-xml, loss.formatting-revisions (tracked formatting changes), loss.comments (a comment anchored between paragraphs). Proofing marks and permission ranges are dropped silently: they describe the editing session, not the document.

Excel

2003Becomes
Worksheet, Table, Row, Cellsheets, rows, cells. ss:Index places an item (a backward index follows the previous item, sml2003.bad-index); ss:Span repeats a column or row; ss:MergeAcross/MergeDown merge
Data ss:TypeNumber; String (inline string); DateTime (ISO 8601 → serial in the workbook's date system; a time alone on 1899-12-31 is a fraction of a day); Boolean; Error
ss:Data with HTML (B, I, U, S, Sub, Sup, Font)rich inline string runs
ss:Formula (R1C1)A1 text through the public formula parser and printer; the cached Data stays as the cached result; nothing is recalculated on open. ss:ArrayRange gives an array formula. Text the parser rejects is sml2003.bad-formula and the value stays as a constant
Styles/Stylecell formats; ss:Parent is resolved (a style with no parent inherits from Default); the number format names of the 2003 documentation (Short Date, Percent, Currency …) map to format codes
Column, Row attributeswidths (points → characters, below), heights, ss:Hidden, ss:StyleID (a cell without a style takes its row's, then its column's)
Names, NamedRange, NamedCelldefined names (workbook and sheet level); Print_Area, Print_Titles, Criteria, Extract, _FilterDatabase become the _xlnm. names
Commentxl/commentsN.xml and a legacy drawing so the note shows
ss:HRefa hyperlink (#Sheet!A1 is internal)
x:ConditionalFormattingcellIs and expression rules with a differential format from the CSS in Format Style
x:DataValidationwhole, decimal, list, date, time, text length and custom rules
x:AutoFilteran auto filter range
x:WorksheetOptionstab selection, gridlines and headings, right-to-left, zoom, frozen panes, protection, page margins, orientation, scale, paper size, centering, header and footer
x:ExcelWorkbookdate system (Date1904), active sheet, structure protection
o:DocumentPropertiescore and app properties

Deviations and choices:

  • Column widths. 2003 stores points; XLSX stores characters of the default font's digit. The reader assumes a 7 pixel digit and 5 pixels of padding at 96 dpi: (points × 96 / 72 − 5) / 7, rounded to two places (48 points is 8.43 characters).
  • Duplicate style IDs. The first definition wins (sml2003.duplicate-style). LibreOffice writes Default twice, the second time in full.
  • Named styles. A named cell style (ss:Name other than Default) becomes a plain cell format; the name is reported as loss.cell-style-names.
  • Sheet names. Characters []:*?/\ are removed, names are cut to 31 characters and made unique ignoring case (sml2003.sheet-name).
  • OpenFormula text. LibreOffice's "Microsoft Excel 2003 XML" export writes of:=[.B2]+[.B3] in ss:Formula. That is not R1C1 and is not read here (OpenFormula belongs to the ODF reader); each such formula is a defect and its cached value is kept.
  • Not carried over: manual page breaks (loss.page-breaks), sorting, pane details beyond the frozen split, printer settings.

Checks and open questions

Checked on the build host: every file the sniffer calls Word or Excel 2003 XML among the committed fixtures and 87 Word and 4 Excel files written by LibreOffice from its own corpus opens with typed defects only; their DOCX/XLSX conversions validate against the pinned ECMA-376 Transitional schemas (1,157 of 1,158 parts; the one miss is xml:space on a spreadsheet t element, which the schema does not declare and Excel itself writes).

Unanswered by Office (to be answered on the oracle machine):

  1. Does Word open the DOCX converted from testdata/xml2003/word-features.xml and lo-word.xml without a repair prompt, and does Word's own conversion of the 2003 file match (paragraph count, numbering labels, revisions, comment text, picture size)?
  2. Does Excel open the XLSX converted from excel-features.xml without repair (comments with the legacy drawing, conditional formats, validation), and does Excel's own "Save as .xlsx" of the 2003 file give the same values, formats and formulas?
  3. Which style wins when a style ID is defined twice, and does a cell without ss:StyleID take its row's or its column's style?
  4. What column width does Excel give ss:Width="64.008" on a machine with the default font (the width formula above is an estimate)?

Regenerate the conversions with tools/Xml2003Probe convert <dir> <out>; tools/xml2003/ holds the inputs LibreOffice converted for the fixtures.