Trying to parse Word docx file as a zip document using Python's xml.elementtree
Question: I'm trying to parse a Windows docx file as a zip file using Python's
xml.elementtree module. I saved the docx file as a zip. Below is what the
document looks like:

    
    
    <?xml version="1.0" encoding="UTF-8" standalone="true"?>
    <?mso-application progid="Word.Document"?>
    -<pkg:package xmlns:pkg="http://schemas.microsoft.com/office/2006/xmlPackage">
    -<pkg:part pkg:padding="512" pkg:contentType="application/vnd.openxmlformats-  package.relationships+xml" pkg:name="/_rels/.rels">
    +<pkg:xmlData>
    </pkg:part>
    +<pkg:part pkg:padding="256" pkg:contentType="application/vnd.openxmlformats-package.relationships+xml" pkg:name="/word/_rels/document.xml.rels">
    -<pkg:part pkg:contentType="application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml" pkg:name="/word/document.xml">
    -<pkg:xmlData>
    -<w:document   xmlns:wps="http://schemas.microsoft.com/office/word/2010/wordprocessingShape" xmlns:wne="http://schemas.microsoft.com/office/word/2006/wordml" xmlns:wpi="http://schemas.microsoft.com/office/word/2010/wordprocessingInk" xmlns:wpg="http://schemas.microsoft.com/office/word/2010/wordprocessingGroup" xmlns:w14="http://schemas.microsoft.com/office/word/2010/wordml" xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" xmlns:w10="urn:schemas-microsoft-com:office:word" xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing" xmlns:wp14="http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:mv="urn:schemas-microsoft-com:mac:vml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mo="http://schemas.microsoft.com/office/mac/office/2008/main" xmlns:wpc="http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas" mc:Ignorable="w14 wp14">
    -<w:body>
    -<w:p w:rsidP="00E65A71" w:rsidRDefault="00E65A71" w:rsidR="00E65A71">
    -<w:r>
     <w:t>Gloss:</w:t>
     </w:r>
     -<w:r>
     <w:tab/>
     </w:r>
    -<w:r w:rsidRPr="00EC6528">
    -<w:rPr>
     <w:noProof/>
     </w:rPr>
     <w:t>the door</w:t>
     </w:r>
     </w:p>
    -<w:p w:rsidP="00E65A71" w:rsidRDefault="00E65A71" w:rsidR="00E65A71">
    -<w:r>
     <w:t xml:space="preserve">Base: </w:t>
     </w:r>
    -<w:r>
     <w:tab/>
     </w:r>
    -<w:r w:rsidRPr="00EC6528">
    -<w:rPr>
     <w:noProof/>
     </w:rPr>
     <w:t>words</w:t>
     </w:r>
    -<w:r>
    

As you can see I've minimized a few of the elements to save space. I'm
interested in the stuff in the

    
    
    <w:document><w:body>
    

elements specifically:

    
    
    <w:r><w:t>
    

that's where the data is that I want to parse. I can't seem to get past the
first element. Below is what's tried to get at that stuff:

    
    
    import xml.etree.ElementTree as ET
    tree = ET.parse('document.xml')
    body = tree.getroot().findall("w")
    #body = tree.getroot().findall(w:t)
    #body = tree.getroot()
    

and also:

    
    
    for child in root:
       print child.tag, child.attrib
    

I've tried that just to see if I could see any of the elements I could then
drill into but that returns nothing. I've also tried other code but I can't
seem to get to the stuff I want. I've programmed a lot in Python put never
used this module to parse XML. I'm using VS studio 2012 with pytools and when
I set a breakpoint and look at the "root" structure I can't seem to drill into
the element I want to get. I can't seem to navigate past the "pkg:package"
stuff. My end goal is to set up a for loop to work through the "" stuff that
will be repeated throughout the document. I've been researching this for a
little while and trying to work through a few of the tutorials so any help is
greatly appreciated! Thanks.


Answer: In Open Office Xml (which is the standard that Microsoft uses for its newer
Office software), the letter in front of the colon in the tag is a prefix and
requires a particular namespace mapping to be processed correctly. For
instance, the tag <w:t> actually requires you to search for the tag string
"{<http://schemas.openxmlformats.org/wordprocessingml/2006/main>}t". The
prefix/namespace is surrounded by curly brackets and the actual tag name
follows at the end. Fortunately, most of what you're probably looking for uses
the namespace that I mentioned above. Here's some sample code that should get
you started in the right direction:

    
    
    import xml.etree.ElementTree as ET
    
    # I find that using a dictionary to map prefixes to namespaces keeps
    # things easier to understand. You can also use the namespaces directly
    # though if you prefer
    NAMESPACE_PREFIXES = {
        'w': 'http://schemas.openxmlformats.org/wordprocessingml/2006/main'
        }  
    
    tree = ET.parse('document.xml')
    root = tree.getroot()
    text_elements = [element for element in root.iter() if element.tag == 
    '{' + NAMESPACE_PREFIXES['w'] + '}t']
    # Equivalent to:
    # text_elements = [element for element in root.iter() if element.tag == 
    # '{http://schemas.openxmlformats.org/wordprocessingml/2006/main}t']
    for text_element in text_elements:
        if text_element.text == 'Hello world!':
            text_element.text = 'Goodbye world!'
    

[Here](http://www.schemacentral.com/sc/ooxml/) are some additional namespaces
for OOXML in case you need them as well.

