2010-11-23 18 views
47

मैं एक xml दस्तावेज़ जिसे मैं Etree.lxmllxml etree xmlparser अवांछित नाम स्थान

का उपयोग कर पार्स करने के लिए कोशिश कर रहा हूँ है हटाने
<Envelope xmlns="http://www.example.com/zzz/yyy"> 
    <Header> 
    <Version>1</Version> 
    </Header> 
    <Body> 
    some stuff 
    <Body> 
<Envelope> 

मेरे कोड है:

path = "path to xml file" 
from lxml import etree as ET 
parser = ET.XMLParser(ns_clean=True) 
dom = ET.parse(path, parser) 
dom.getroot() 

मैं dom.getroot प्राप्त करने के लिए प्रयास करते हैं() मैं:

<Element {http://www.example.com/zzz/yyy}Envelope at 28adacac> 

हालांकि मैं केवल हैं:

<Element Envelope at 28adacac> 

जब मैं कर

dom.getroot().find("Body") 

मैं कुछ भी नहीं लौटे मिलता है। हालांकि, जब मैं

dom.getroot().find("{http://www.example.com/zzz/yyy}Body") 

मुझे परिणाम मिल गया।

मैंने सोचा कि ns_clean = पारदर्शी के लिए सही यह रोक देगा।

कोई विचार?

उत्तर

48
import io 
import lxml.etree as ET 

content='''\ 
<Envelope xmlns="http://www.example.com/zzz/yyy"> 
    <Header> 
    <Version>1</Version> 
    </Header> 
    <Body> 
    some stuff 
    </Body> 
</Envelope> 
'''  
dom = ET.parse(io.BytesIO(content)) 

आप नाम स्थान-अवगत xpath पद्धति का उपयोग करके नोड्स पा सकते हैं :

body=dom.xpath('//ns:Body',namespaces={'ns':'http://www.example.com/zzz/yyy'}) 
print(body) 
# [<Element {http://www.example.com/zzz/yyy}Body at 90b2d4c>] 

यदि आप वास्तव में नामस्थान को हटाना चाहते हैं, तो आप एक XSL रूपांतरण इस्तेमाल कर सकते हैं:

# 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) 
dom=transform(dom) 

यहाँ हम देखते हैं नाम स्थान हटा दिया गया है:

print(dom.find("Body")) 
# <Element Body at 8506cd4> 
+0

body = dom.xpath ('// ns: body', namespaces = {'ns': 'http: //www.xxx.com/zzz/yyy'}) परफेक्ट! सभी नामस्थानों को हटाने के लिए – Mark

+9

एक्सएसएलटी। बस मैं जो खोज रहा था, प्रतिभा। –

+0

FYI यदि Python3 का उपयोग कर आपको पहले xslt स्ट्रिंग को एन्कोड करने की आवश्यकता होगी। यानी xslt_doc = ET.parse (io.BytesIO (str.encode (xslt)) – AZhao

-1

आप repr() कॉल का परिणाम दिखा रहे हैं। जब आप प्रोग्राम के माध्यम से पेड़ के माध्यम से स्थानांतरित होते हैं, तो आप बस नामस्थान को अनदेखा करना चुन सकते हैं।

+4

नहीं, जब मैं करता हूं - dom.getroot()। ढूंढें ("बॉडी") - मुझे कोई परिणाम नहीं मिलता है। तत्व प्राप्त करने का एकमात्र तरीका यह है - dom.getroot() .find ('{http://www.xxx.com/zzz/yyy} body') – Mark

24

Xpath उपयोग करके देखें:

dom.xpath("//*[local-name() = 'Body']") 

लिया (और सरलीकृत) this page से, के तहत "xpath() विधि" खंड

+0

यह सबसे अच्छा समाधान है। वोट ऊपर! – vangheem

3

पिछले समाधान:

print(ET.tostring(dom)) 
# <Envelope> 
# <Header> 
#  <Version>1</Version> 
# </Header> 
# <Body> 
#  some stuff 
# </Body> 
# </Envelope> 

तो अब शारीरिक नोड इस तरह से पा सकते हैं https://bitbucket.org/olauzanne/pyquery/issue/17 से छोटे प्रयासों के साथ नामस्थानों से बचने में आपकी मदद कर सकते हैं

pyquery उपयोग करने से पहले अपने xml करने के लिए xml.replace(' xmlns:', ' xmlnamespace:') लागू तो lxml नामस्थान

आपके मामले में अनदेखी करेंगे, xml.replace(' xmlns="', ' xmlnamespace="') प्रयास करें। हालांकि, यदि शरीर में स्ट्रिंग की अपेक्षा की जाती है तो आपको कुछ और जटिल की आवश्यकता हो सकती है।

+2

यह आश्चर्यजनक है। आपने अपना जीवन बदल दिया है, धन्यवाद। (पीएस, जो भी एक्सएमएल नेमस्पेस, wtf डिजाइन किया गया है?) –

+11

स्ट्रिंग मुंगिंग हमेशा पागलपन का मार्ग है। सामान्य मामले में, यह उत्तर गलत है। मान लीजिए कि आप इस सटीक प्रश्न के आरएसएस फ़ीड को स्वरूपित कर रहे हैं - परिणाम लोगों को 'xml.replace (' xmlnamespace = "',' xmlnamespace =" ')' 'बताएगा ... – bukzor