2011-08-09 5 views
5

मेरे पास एक विशाल एक्सएमएल फ़ाइल (1 गीग) है। मैं कुछ तत्वों (प्रविष्टियों) को एक ही शीर्षलेख और विनिर्देशों के साथ किसी अन्य फ़ाइल में स्थानांतरित करना चाहता हूं।lxml.etree.tostring (तत्व) को पायथन में नामस्थान लिखने के लिए कैसे बताना है?

चलो कहते हैं कि मूल फ़ाइल टैग <to_move> के साथ इस प्रविष्टि शामिल करते हैं:

<?xml version="1.0" encoding="ISO-8859-1"?> 
<!DOCTYPE some SYSTEM "some.dtd"> 
<some> 
... 
<to_move date="somedate"> 
    <child>some text</child> 
    ... 
... 
</to_move> 
... 
</some> 

मैं lxml.etree.iterparse का उपयोग फ़ाइल के माध्यम से पुनरावृति करने के लिए। ठीक काम करता है। जब मैं टैग <to_move> साथ तत्व मिल जाए, मान लेते हैं यह चर element में संग्रहीत किया जाता रहा

new_file.write(etree.tostring(element)) 

करते हैं लेकिन इस

<?xml version="1.0" encoding="ISO-8859-1"?> 
<!DOCTYPE some SYSTEM "some.dtd"> 
<some> 
... 
<to_move xmlns:="some" date="somedate"> # <---- Here is the problem. I don't want the namespace. 
    <child>some text</child> 
    ... 
... 
</to_move> 
... 
</some> 

तो परिणाम में सवाल यह है: etree.tostring बताने के लिए कैसे () xmlns:="some" लिखना नहीं है। क्या यह संभव है? मैं lxml.etree के api- प्रलेखन के साथ struggeled, लेकिन मुझे एक संतोषजनक जवाब नहीं मिल सका।

यह मैं etree.trostring के लिए क्या मिला है:

tostring(element_or_tree, encoding=None, method="xml", 
xml_declaration=None, pretty_print=False, with_tail=True, 
standalone=None, doctype=None, exclusive=False, with_comments=True) 

अपने एक्सएमएल पेड़ की एक इनकोडिंग स्ट्रिंग प्रतिनिधित्व करने के लिए एक तत्व को क्रमानुसार।

मेरे लिए tostring() के पैरामीटर में से प्रत्येक में मदद करने के लिए प्रतीत नहीं होता है। कोई सुझाव या सुधार?

उत्तर

5

मैं अक्सर इस तरह इसके लिए एक अन्य नाम बनाने के लिए एक नाम स्थान हड़पने:

someXML = lxml.etree.XML(someString) 
if ns is None: 
     ns = {"m": someXML.tag.split("}")[0][1:]} 
someid = someXML.xpath('.//m:ImportantThing//m:ID', namespaces=ns) 

आप कर सकता हैका उपयोग करने के बाद इसे साफ़ करने वाले रेगेक्स को बनाने के लिए नेमस्पेस को पकड़ने के समान कुछ।

या आप इनपुट स्ट्रिंग को साफ़ कर सकते हैं। पहली जगह पाएं, जांचें कि क्या यह xmlns के बाद है, यदि हां, तो स्पेस को हटाए जाने पर, पूरे एक्सएमएलएन को अगले स्थान तक बिट करें। तब तक दोहराएं जब तक कोई और रिक्त स्थान या xmlns घोषणाएं न हों। लेकिन पहले > से पहले मत जाओ।

2

remove namespaces with XSLT का एक तरीका होता है:

import io 
import lxml.etree as ET 


def remove_namespaces(doc): 
    # http://wiki.tei-c.org/index.php/Remove-Namespaces.xsl 
    xslt='''<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml" indent="no"/> 

    <xsl:template match="/|comment()|processing-instruction()"> 
     <xsl:copy> 
      <xsl:apply-templates/> 
     </xsl:copy> 
    </xsl:template> 

    <xsl:template match="*"> 
     <xsl:element name="{local-name()}"> 
      <xsl:apply-templates select="@*|node()"/> 
     </xsl:element> 
    </xsl:template> 

    <xsl:template match="@*"> 
     <xsl:attribute name="{local-name()}"> 
      <xsl:value-of select="."/> 
     </xsl:attribute> 
    </xsl:template> 
    </xsl:stylesheet> 
    ''' 

    xslt_doc = ET.parse(io.BytesIO(xslt)) 
    transform = ET.XSLT(xslt_doc) 
    doc = transform(doc) 
    return doc 

doc = ET.parse('data.xml') 
doc = remove_namespaces(doc) 
print(ET.tostring(doc)) 

पैदावार

<some> 

<to_move date="somedate"> 
    <child>some text</child> 
</to_move> 

</some> 
+0

मैं नामस्थानों के पीछे * महान विचार * समझता हूं। :-) लेकिन मेरे इस विशेष मामले में इसमें कोई लाभ नहीं है। इसका मतलब यह नहीं है कि मैं हमेशा उन्हें अनदेखा कर दूंगा। :-) धन्यवाद! – Aufwind

3

यह 'unutbu' द्वारा दिए गए उत्तर के लिए टिप्पणी में अधिक है जिसमें नामस्थान को साफ करने के सुझाव को उदाहरण दिए बिना वांछित किया गया था। यह हो सकता है कि आप जो खोज रहे हैं ...

from lxml import objectify 
objectify.deannotate(root, cleanup_namespaces=True) 
+0

यह किसी भी नामस्थान को नहीं हटाएगा। दस्तावेज़ों से: "'py: pytype' और/या 'xsi: type' विशेषताएँ और/या 'xsi: nil' विशेषताओं को हटाकर किसी XML पेड़ के तत्वों को दोबारा एनोटेट करें।" –

+1

यह लगभग मेरे लिए काम करता है, मेरे पास अभी भी परिणामी स्ट्रिंग में 'xmlns' विशेषता है, क्या इसका पुन: उपयोग किए बिना भी छुटकारा पाने का कोई तरीका है? – Dettorer

+0

यह काम करता है।साथ ही, 'ऑब्जेक्टिफ़ाई' और पैरामीटर 'एनोटेट = गलत' के साथ तत्व उत्पन्न करना भी उदाहरण के लिए: उदाहरण के लिए: 'myE = objectify.ElementMaker (annotate = गलत)' और फिर 'x = myE.rootElem()'; आप 'etree.tostring (x, method = 'xml') का उपयोग करके इसे क्रमबद्ध कर सकते हैं और वापस '' – miha

संबंधित मुद्दे