2017-01-30 5 views
4

Ich baue Openoffice-Dokumente. Ich habe ein Gerüst, mit dem ich meine content.xml-Datei erstelle. Der Inhalt-scaffold.xml Datei wird im Dateisystem gespeichert und sieht wie folgt aus:ElementTree: Warum werden meine Namespace-Deklarationen entfernt?

<?xml version="1.0" encoding="UTF-8"?> 
    <office:document-content 
    xmlns:anim="urn:oasis:names:tc:opendocument:xmlns:animation:1.0" 
    xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" 
    xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" 
    xmlns:db="urn:oasis:names:tc:opendocument:xmlns:database:1.0" 
    xmlns:dc="http://purl.org/dc/elements/1.1/" 
    xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" 
    xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" 
    xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" 
    xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" 
    xmlns:grddl="http://www.w3.org/2003/g/data-view#" 
    xmlns:manifest="urn:oasis:names:tc:opendocument:xmlns:manifest:1.0" 
    xmlns:math="http://www.w3.org/1998/Math/MathML" 
    xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" 
    xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" 
    xmlns:odf="http://docs.oasis-open.org/ns/office/1.2/meta/odf#" 
    xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" 
    xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" 
    xmlns:pkg="http://docs.oasis-open.org/ns/office/1.2/meta/pkg#" 
    xmlns:presentation="urn:oasis:names:tc:opendocument:xmlns:presentation:1.0" 
    xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" 
    xmlns:smil="urn:oasis:names:tc:opendocument:xmlns:smil-compatible:1.0" 
    xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" 
    xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" 
    xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" 
    xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" 
    xmlns:xforms="http://www.w3.org/2002/xforms" 
    xmlns:xhtml="http://www.w3.org/1999/xhtml" 
    xmlns:xlink="http://www.w3.org/1999/xlink" 
    office:version="1.2"> 

    <office:automatic-styles> 

    <style:style style:family="text" style:name="Strong"> 
     <style:text-properties 
     fo:color="#000000" 
     fo:font-weight="bold" /> 
    </style:style> 

    </office:automatic-styles> 


    <office:body> 
    <office:text> 
     <!-- content will go here --> 
    </office:text> 
    </office:body> 

</office:document-content> 

Die Idee ist, dass ich diese xml nehmen und Sachen in das Büro injizieren: Text-Tag (in Python), dann machen Sie es zurück. In diesem Beispiel injiziere ich einen einfachen Text: p tag.

document_content = ElementTree.parse('content-scaffold.xml').getroot() 
office_body = document_content.find('office:body', NAMESPACES) 
office_text = office_body.find('office:text', NAMESPACES) 
p = ElementTree.SubElement(office_text, 'text:p') 
p.text = "Hello" 

Dies ist jedoch, was die Namensräume Erklärungen wie einmal gerendert aussehen:

<office:document-content 
xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" 
xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" 
xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" 
office:version="1.2"> 

Diese in den folgenden Fehlern führt:

Namespace prefix text on p is not defined

Es ist ziemlich klar, dass ElementTree nur Xmlns zu halten ist Deklarationen, die benötigt werden (in meinem Fall fo, office und style, da sie die einzigen sind, die in content-scaffold.xml vorhanden sind), und es ist ziemlich ordentlich. Allerdings möchte ich sie alle wirklich, um alle Namespaces nutzen zu können.

Irgendeine Idee, wie man ElementTree erzwingt, um sie alle zu behalten? Oder denke ich das von Anfang an falsch? Ich bin offen für alternative Lösungen.

Hinweis: Ich verwende Python 3 und ElementTree

Dank

+0

Gefunden eine sehr ähnliche Frage: http://stackoverflow.com/q/24557151/407651 – mzjn

Antwort

2

ElementTree ist eher schwach, wenn es die Handhabung zu Namespace kommt. Allerdings kann getan werden, was Sie fordern (aber es ist ein wenig Aufwand):

from xml.etree import ElementTree as ET 

NAMESPACES = {"anim": "urn:oasis:names:tc:opendocument:xmlns:animation:1.0", 
    "chart": "urn:oasis:names:tc:opendocument:xmlns:chart:1.0", 
    "config": "urn:oasis:names:tc:opendocument:xmlns:config:1.0", 
    "db": "urn:oasis:names:tc:opendocument:xmlns:database:1.0", 
    "dc": "http://purl.org/dc/elements/1.1/", 
    "dr3d": "urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0", 
    "draw": "urn:oasis:names:tc:opendocument:xmlns:drawing:1.0", 
    "fo": "urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0", 
    "form": "urn:oasis:names:tc:opendocument:xmlns:form:1.0", 
    "grddl": "http://www.w3.org/2003/g/data-view#", 
    "manifest": "urn:oasis:names:tc:opendocument:xmlns:manifest:1.0", 
    "math": "http://www.w3.org/1998/Math/MathML", 
    "meta": "urn:oasis:names:tc:opendocument:xmlns:meta:1.0", 
    "number": "urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0", 
    "odf": "http://docs.oasis-open.org/ns/office/1.2/meta/odf#", 
    "of": "urn:oasis:names:tc:opendocument:xmlns:of:1.2", 
    "office": "urn:oasis:names:tc:opendocument:xmlns:office:1.0", 
    "pkg": "http://docs.oasis-open.org/ns/office/1.2/meta/pkg#", 
    "presentation": "urn:oasis:names:tc:opendocument:xmlns:presentation:1.0", 
    "script": "urn:oasis:names:tc:opendocument:xmlns:script:1.0", 
    "smil": "urn:oasis:names:tc:opendocument:xmlns:smil-compatible:1.0", 
    "style": "urn:oasis:names:tc:opendocument:xmlns:style:1.0", 
    "svg": "urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0", 
    "table": "urn:oasis:names:tc:opendocument:xmlns:table:1.0", 
    "text": "urn:oasis:names:tc:opendocument:xmlns:text:1.0", 
    "xforms": "http://www.w3.org/2002/xforms", 
    "xhtml": "http://www.w3.org/1999/xhtml", 
    "xlink": "http://www.w3.org/1999/xlink"} 

document_content = ET.parse('content-scaffold.xml').getroot() 
office_body = document_content.find('office:body', NAMESPACES) 
office_text = office_body.find('office:text', NAMESPACES) 
p = ET.SubElement(office_text, 'text:p') 
p.text = "Hello" 

for prefix, uri in NAMESPACES.items(): 
    ET.register_namespace(prefix, uri)   # Ensure correct prefixes in output 
    if prefix not in ("office", "fo", "style"): # Prevent duplicate ns declarations 
     document_content.set("xmlns:" + prefix, uri) # Add ns declarations to root element 

ET.ElementTree(document_content).write("output.xml") 

Dieser Code ein Ergebnisdokument mit allen Namespace-Deklarationen erhalten schaffen.


Hier ist, wie kann es mit lxml erfolgen:

from lxml import etree as ET 

NAMESPACES = {"office": "urn:oasis:names:tc:opendocument:xmlns:office:1.0"} 

document_content = ET.parse('content-scaffold.xml') 
office_body = document_content.find('office:body', NAMESPACES) 
office_text = office_body.find('office:text', NAMESPACES) 
p = ET.SubElement(office_text, '{urn:oasis:names:tc:opendocument:xmlns:text:1.0}p') 
p.text = "Hello" 

document_content.write("output.xml") 

Beachten Sie, dass Sie den Namen des Elements mit Clark notation in SubElement() zu bieten haben.

+0

Ich endete mit lxml wie Sie vorgeschlagen und es hat funktioniert. Vielen Dank – MonsieurNinja

Verwandte Themen