8

I am transforming word documents to xml to compare them using the following code:

word = win32com.client.Dispatch('Word.Application')
wd = word.Documents.Open(inFile)
# Converts the word infile to xml outfile
wd.SaveAs(outFile,11)
wd.Close()
dom=parse(outFile)

The xml file I get looks like:

<?xml version="1.0" encoding="utf-8"?>
<?mso-application progid="Word.Document"?>
<w:wordDocument w:embeddedObjPresent="no" w:macrosPresent="no" w:ocxPresent="no" xml:space="preserve" xmlns:aml="http://schemas.microsoft.com/aml/2001/core" xmlns:dt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:sl="http://schemas.microsoft.com/schemaLibrary/2003/core" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:w="http://schemas.microsoft.com/office/word/2003/wordml" xmlns:w10="urn:schemas-microsoft-com:office:word" xmlns:wne="http://schemas.microsoft.com/office/word/2006/wordml" xmlns:wpc="http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas" xmlns:wsp="http://schemas.microsoft.com/office/word/2003/wordml/sp2" xmlns:wx="http://schemas.microsoft.com/office/word/2003/auxHint">
    <w:ignoreSubtree w:val="http://schemas.microsoft.com/office/word/2003/wordml/sp2"/>
    <w:shapeDefaults>
        <o:shapedefaults spidmax="1027" v:ext="edit"/>
        <o:shapelayout v:ext="edit">
            <o:idmap data="1" v:ext="edit"/>
        </o:shapelayout>
    </w:shapeDefaults>
    <w:body>
        <wx:sect>
            <w:tbl>

            <w:tblGrid>
                <w:gridCol w:w="200"/>
                                       ...
            </w:tblGrid>

                <w:pict>
                        <v:shapetype coordsize="21600,21600" filled="f" id="_x0000_t75" o:preferrelative="t" o:spt="75" path="m@4@5l@4@11@9@11@9@5xe" stroked="f">
                            <v:stroke joinstyle="miter"/>
                            <v:formulas>
                                <v:f eqn="if lineDrawn pixelLineWidth 0"/>
                                ...
                            </v:formulas>
                            <v:path gradientshapeok="t" o:connecttype="rect" o:extrusionok="f"/>
                            <o:lock aspectratio="t" v:ext="edit"/>
                        </v:shapetype>
                        <v:shape id="Picture" o:spid="_x0000_s1026" style="position:absolute;left:0;text-align:left;margin-left:0;margin-top:0;width:400pt;height:40pt;z-index:1;visibility:visible;mso-wrap-style:square;mso-wrap-distance-left:0;mso-wrap-distance-top:0;mso-wrap-distance-right:0;mso-wrap-distance-bottom:0;mso-position-horizontal:left;mso-position-horizontal-relative:text;mso-position-vertical:absolute;mso-position-vertical-relative:line" type="#_x0000_t75">
                            <v:imagedata o:title="" src="wordml://03000001.png"/>
                            <w10:wrap anchory="line"/>
                            <w10:anchorlock/>
                        </v:shape>
                </w:pict> 
                                      ...

I can't use xpath function (lxml library) when I try for example :

import lxml.etree as et
tree = et.parse(xmlFile)
for elt in tree.xpath("//w:gridCol"):
     elt.getparent().remove(elt)

I get the following error:

 for elt in tree.xpath("//w:gridCol"):
  File "lxml.etree.pyx", line 2029, in lxml.etree._ElementTree.xpath (src/lxml/lxml.etree.c:45934)
  File "xpath.pxi", line 379, in lxml.etree.XPathDocumentEvaluator.__call__ (src/lxml/lxml.etree.c:114389)
  File "xpath.pxi", line 242, in lxml.etree._XPathEvaluatorBase._handle_result (src/lxml/lxml.etree.c:113063)
  File "xpath.pxi", line 227, in lxml.etree._XPathEvaluatorBase._raise_eval_error (src/lxml/lxml.etree.c:112894)
XPathEvalError: Undefined namespace prefix

I did some research and I guess it's a namespace matter, but I don't know how to fix it?

2
  • Register the namespace (see stackoverflow.com/a/14853417/3190413) or ignore them using //*[local-name()='gridCol'] Commented Jun 4, 2014 at 13:39
  • @helderdarocha ignoring namespace works fine Thanks for the answer Commented Jun 4, 2014 at 16:30

1 Answer 1

14

In this code:

for elt in tree.xpath("//w:gridCol"):

w: isn't a namespace; it's a namespace prefix which is effectively shorthand for the actual namespace, http://schemas.microsoft.com/office/word/2003/wordml. If you want to search for elements in this namespace using the xpath method, you need to provide it with a mapping of namespace prefixes to namespaces:

tree.xpath("//w:gridCol", namespaces={
  'w': 'http://schemas.microsoft.com/office/word/2003/wordml',
  })

Also, note that there is no requirement that you use the same namespace prefix. The following would find the same elements:

tree.xpath("//bob:gridCol", namespaces={
  'bob': 'http://schemas.microsoft.com/office/word/2003/wordml'
  })
Sign up to request clarification or add additional context in comments.

3 Comments

The elt already knows the namespaces and their mapping (see elt.nsmap), so why doesn't it use them?
That seems like a good question for the developer. I haven't examined the code in that level of detail.
I reconsidered this with a coworker and we came to the conclusion that it wouldn't be correct to reuse the .nsmap. The ns-prefixes can change from instance to instance since the sender of the XML can choose them freely. If we write code using a fixed ns-prefix, that's okay as long as we also provide a fixed map which associates this ns-prefix with the namespace-uri. Relying on the .nsmap would just be insufficient.

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.