पथ

2015-04-01 5 views
9

पर आधारित XML फ़ाइल टेक्स्ट संपादित करें मेरे पास एक XML फ़ाइल है (उदा। Jerry.xml) जिसमें नीचे दिया गया कुछ डेटा शामिल है।पथ

<data> 
<country name="Peru"> 
    <rank updated="yes">2</rank> 
    <language>english</language> 
    <currency>1.21$/kg</currency> 
    <gdppc month="06">141100</gdppc> 
    <gdpnp month="10">2.304e+0150</gdpnp> 
    <neighbor name="Austria" direction="E"/> 
    <neighbor name="Switzerland" direction="W"/> 
</country> 
<country name="Singapore"> 
    <rank updated="yes">5</rank> 
    <language>english</language> 
    <currency>4.1$/kg</currency> 
    <gdppc month="05">59900</gdppc> 
    <gdpnp month="08">1.9e-015</gdpnp> 
    <neighbor name="Malaysia" direction="N"/> 
</country> 

मैंने नीचे दिए गए कोड का उपयोग करके ऊपर दिए गए एक्सएमएल से कुछ चयनित ग्रंथों के पूर्ण पथ निकाले। कारण post में दिए गए हैं।

def extractNumbers(path, node): 
    nums = [] 

    if 'month' in node.attrib: 
     if node.attrib['month'] in ['05', '06']: 
      return nums 

    path += '/' + node.tag 
    if 'name' in node.keys(): 
     path += '=' + node.attrib['name'] 

    elif 'year' in node.keys(): 
     path += ' ' + 'month' + '=' + node.attrib['month'] 
    try: 
     num = float(node.text) 
     nums.append((path, num)) 
    except (ValueError, TypeError): 
     pass 
    for e in list(node): 
     nums.extend(extractNumbers(path, e)) 
    return nums 

tree = ET.parse('jerry.xml') 
nums = extractNumbers('', tree.getroot()) 
print len(nums) 
print nums 

यह मैं तत्वों मैं नीचे के रूप में (जैसे hrong.csv) सीएसवी के colomn 1 में दिखाया गया बदलने की जरूरत के स्थान देता है।

Path              Text1  Text2  Text3  Text4  Text5 
'/data/country name=singapore/gdpnp month=08';   5.2e-015; 2e-05;  8e-06;  9e-04;  0.4e-05; 
'/data/country name=peru/gdppc month=06';     0.04;  0.02;  0.15;  3.24;  0.98;             

मैं ऊपर hrong.csv के स्तंभ 2 में उन लोगों के, स्तंभ 1 में तत्वों के स्थान पर आधारित द्वारा मूल एक्सएमएल फ़ाइल (jerry.xml) के तत्वों के पाठ को प्रतिस्थापित करना चाहते हैं।

मैं अजगर के लिए नौसिखिया हूं और महसूस करता हूं कि मैं सबसे अच्छा दृष्टिकोण नहीं उपयोग कर रहा हूं। दिशा निर्देश के संबंध में मैं किसी भी मदद की सराहना करता हूं। मुझे मूल रूप से केवल कुछ चयनित ग्रंथों को किसी XML फ़ाइल के नोड्स को पार्स करने की आवश्यकता है, चयनित टेक्स्ट नोड्स को संशोधित करें और प्रत्येक फ़ाइल को सहेजें।

धन्यवाद

+0

"केवल कुछ चयनित टेक्स्ट नोड्स को पार्स करने की आवश्यकता है" - कौन सा? आप उन्हें कैसे चुनते हैं? – snapshoe

+0

@ स्नैपशो मुझे केवल उन नोड्स पर विचार करने की आवश्यकता है जिनके ग्रंथ फ्लोट-सक्षम हैं। अधिक स्पष्टीकरण [लिंक] के लिए कृपया पहले पोस्ट देखें (http: // stackoverflow।कॉम/प्रश्न/28568823/पार्स-एंड-गिनती-न्यूमेरिक-केवल-एक्सएमएल-टेक्स्ट-इन-ई -00-या -01) – Mia

+0

लेकिन ऐसा लगता है कि आप केवल महीनों '05' और '06' का चयन कर रहे हैं? क्या वे एकमात्र महीने हैं? अन्य महीनों जैसे '08' और '10' लागू नहीं होते ??? – snapshoe

उत्तर

5

ऐसा करने के लिए मॉड्यूल के XPath क्षमताओं का उपयोग करने में सक्षम होना चाहिए:

import xml.etree.ElementTree as ET 
tree = ET.parse('jerry.xml') 
root = tree.getroot() 
for data in root.findall(".//country[@name='singapore']/gdpnp[@month='08']"): 
    data.text = csv_value 

tree.write("filename.xml") 

तो तुम सीएसवी XPath नियमों के लिए परिभाषित मिलान करने के लिए पथ को फिर से लिखने की जरूरत है मॉड्यूल (Supported XPath rules देखें)।

+0

क्या टेक्स्ट नोड्स के XPath परिभाषित पथ को स्वचालित रूप से पुनर्प्राप्त करने का कोई तरीका है? मैंने यहां वर्णित विधि का उपयोग किया [लिंक] (http://stackoverflow.com/questions/28568823/parse-and-count-numeric-only-xml-text-including-e-00-or-e01)। – Mia

+0

नहीं, लेकिन लिंक में दिए गए जवाब में पहले से ही xpath नियम के लिए सभी जानकारी शामिल है। आपको केवल इसे थोड़ा लिखना होगा ताकि यह उपरोक्त मेरे उदाहरण से मेल खा सके। – rfkortekaas

+0

त्वरित प्रश्न @rfkortekaas। क्या लिखित फाइलों को गतिशील रूप से नामित करना संभव है? समस्या यह है कि मुझे इनमें से 10,000 बनाई गई XML फ़ाइलों को लिखना है। धन्यवाद – Mia

2

सभी का फ़ाइस्ट, documentation of how to modify an XML। अब, यहाँ अपने ही उदाहरण है:

import xml.etree.ElementTree as ET 

s = """ 
<root> 
    <parent attribute="value"> 
     <child_1 other_attr="other_value">child text</child_1> 
     <child_2 yet_another_attr="another_value">more child text</child_2> 
    </parent> 
</root> 
""" 

root = ET.fromstring(s) 

for parent in root.getchildren(): 
    parent.attrib['attribute'] = 'new value' 
    for child in parent.getchildren(): 
     child.attrib['new_attrib'] = 'new attribute for {}'.format(child.tag) 
     child.text += ', appended text!' 

>>> ET.dump(root) 
<root> 
    <parent attribute="new value"> 
     <child_1 new_attrib="new attribute for child_1" other_attr="other_value">child text, appended text!</child_1> 
     <child_2 new_attrib="new attribute for child_2" yet_another_attr="another_value">more child text, appended text!</child_2> 
    </parent> 
</root> 

और आप के रूप में अच्छी Xpath के साथ ऐसा कर सकते हैं।

>>> root.find('parent/child_1[@other_attr]').attrib['other_attr'] = 'found it!' 
>>> ET.dump(root) 
<root> 
    <parent attribute="new value"> 
     <child_1 new_attrib="new attribute for child_1" other_attr="found it!">child text, appended text!</child_1> 
     <child_2 new_attrib="new attribute for child_2" yet_another_attr="another_value">more child text, appended text!</child_2> 
    </parent> 
</root> 
2

मैं एक रिश्तेदार फ़ाइल में पढ़ने के आधार पर xpath उत्पन्न करने के लिए अपने extractNumbers समारोह और अन्य कोड बदल दिया है।

import xml.etree.ElementTree as ET 

def extractNumbers(path, node): 
    nums = [] 
    # You'll want to store a relative, rather than an absolute path. 
    if not path: # This is the root node, store the // Predicate to look at all root's children. 
     path = ".//" 
    else: # This is not the root node 
     if 'month' in node.attrib: 
      if node.attrib['month'] in ['05', '06']: 
       return nums 

     path += node.tag 
     if 'name' in node.keys(): 
      path += '[@name="{:s}"]/'.format(node.attrib['name']) 
     elif 'year' in node.keys(): 
      path += '[@month="{:s}"]/'.format(node.attrib['month']) 
     try: 
      num = float(node.text) 
      nums.append((path, num)) 
     except (ValueError, TypeError): 
      pass 
    # Descend into the node's child nodes 
    for e in list(node): 
     nums.extend(extractNumbers(path, e)) 
    return nums 

tree = ET.parse('jerry.xml') 
nums = extractNumbers('', tree.getroot()) 

इस बिंदु पर आपके पास "पथ, संख्या" के tuples के साथ आबादी की एक संख्या है। आप अपने सीएसवी में पथ लिखना चाहेंगे। निम्नलिखित में, मैंने माना है कि आप हाथ से पहले टेक्स्ट 1, टेक्स्ट 2 और टेक्स्ट 3 मानों को जानते हैं, और इसलिए मैंने प्रत्येक पंक्ति में 'foo', 'bar', 'baz' लिखा है।

import csv 
# Write the CSV file with the data found from extractNumbers 
with open('records.csv', 'w') as records: 
    writer = csv.writer(records, delimiter=';') 
    writer.writerow(['Path', 'Text1', 'Text2', 'Text3']) 
    for entry in nums: 
     # Ensure that you're writing a relative xpath 
     rel_path = entry[0] 
     # you will want to "Text1", 'foo' below, to be an appropriate value, as it will be written into the xml below 
     writer.writerow([rel_path, 'foo', 'bar', 'baz']) 

अब आप निम्नलिखित CSV फ़ाइल

Path;Text1;Text2;Text3 
".//country[@name=""Peru""]/rank";foo;bar;baz 
".//country[@name=""Peru""]/gdpnp";foo;bar;baz 
".//country[@name=""Singapore""]/rank";foo;bar;baz 
".//country[@name=""Singapore""]/gdpnp";foo;bar;baz 

निम्न कोड में, आप csv फ़ाइल CSV फ़ाइल पढ़ें पढ़ा जाएगा होगा, और उचित मान को बदलने के लिए पथ स्तंभ का उपयोग

import csv 
import xml.etree.ElementTree as ET 
with open('records.csv', 'r') as records: 
    reader = csv.reader(records, delimiter=';') 
    for row in reader: 
     if reader.line_num == 1: continue # skip the row of headers 
     for data in tree.findall(row[0]): 
      data.text = row[1] 
tree.write('jerry_new.xml') 

आप jerry_new.xml में निम्न परिणाम होगा

<data> 
    <country name="Peru"> 
     <rank updated="yes">foo</rank> 
     <language>english</language> 
     <currency>1.21$/kg</currency> 
     <gdppc month="06">141100</gdppc> 
     <gdpnp month="10">foo</gdpnp> 
     <neighbor direction="E" name="Austria" /> 
     <neighbor direction="W" name="Switzerland" /> 
    </country> 
    <country name="Singapore"> 
     <rank updated="yes">foo</rank> 
     <language>english</language> 
     <currency>4.1$/kg</currency> 
     <gdppc month="05">59900</gdppc> 
     <gdpnp month="08">foo</gdpnp> 
     <neighbor direction="N" name="Malaysia" /> 
    </country> 
</data> 
संबंधित मुद्दे