2011-05-13 7 views
4

xml.etree.ElementTree를 사용하여 xml을 구문 분석하고 내용을 검색 한 다음이를 다른 xml에 쓰는 데 성공했습니다. 그러나, 나는 단 하나의 꼬리표의 안쪽에 원본으로 일했다. 아래의 예는,xml 내용 검색/바꾸기

1) XML을 검색하고 "ATTR"태그 사이에 모든 것을 잡아 :

import os, sys, glob, xml.etree.ElementTree as ET 
path = r"G:\\63D RRC GIS Data\\metadata\\general\\2010_contract" 
for fn in os.listdir(path): 
    filepaths = glob.glob(path + os.sep + fn + os.sep + "*overall.xml") 
    for filepath in filepaths: 
     (pa, filename) = os.path.split(filepath) 
     ####use this section to grab element text from old, archived metadata files; this text then gets put into current, working .xml### 
     root = ET.parse(pa + os.sep + "archive" + os.sep + "base_metadata_overall.xml").getroot() 

     iterator = root.getiterator() 
     for item in iterator: 
      if item.tag == "abstract": 
       correct_abstract = item.text 

     root2 = ET.parse(pa + os.sep + "base_metadata_overall.xml").getroot() 

     iterator2 = root2.getiterator("descript") 
     for item in iterator2: 
      if item.tag == "abstract": 
       old_abstract = item.find("abstract") 
       old_abstract_text = old_abstract.text 
       item.remove(old_abstract) 
       new_symbol_abstract = ET.SubElement(item, "title") 
       new_symbol_abstract.text = correct_abstract     
     tree = ET.ElementTree(root2) 
     tree.write(pa + os.sep + "base_metadata_overall.xml") 
     print "created --- " + filename + " metadata" 

그러나 지금, 내가 필요

<attr><attrlabl Sync="TRUE">OBJECTID</attrlabl><attalias Sync="TRUE">ObjectIdentifier</attalias><attrtype Sync="TRUE">OID</attrtype><attwidth Sync="TRUE">4</attwidth><atprecis Sync="TRUE">0</atprecis><attscale Sync="TRUE">0</attscale><attrdef Sync="TRUE">Internal feature number.</attrdef></attr> 

2) 지금, 나는 필요 다른 XML을 열고 같은 "attr"태그 사이의 모든 내용을 검색하고 위의 내용으로 바꿉니다.

기본적으로 이전에 내가 뭘하고 있었는지, 하위 요소, 속성 등을 무시하고 "attr"태그 사이를 바꾸어 텍스트처럼 취급합니다.

감사합니다.

저와 함께하시기 바랍니다,이 포럼은 조금 다른 (게시) 다음하는 데 사용됩니다! 심지어 ATTR의의 #은 DIF 경우, 그러나 새로운 .XML 에 수출하는 방법을 알아 냈어,

import os, sys, glob, re, xml.etree.ElementTree as ET 
from lxml import etree 

path = r"C:\\temp\\python\\xml" 
for fn in os.listdir(path): 
    filepaths = glob.glob(path + os.sep + fn + os.sep + "*overall.xml") 
    for filepath in filepaths: 
      (pa, filename) = os.path.split(filepath) 

      xml = open(pa + os.sep + "attributes.xml") 
      xmltext = xml.read() 
      correct_attrs = re.findall("<attr> (.*?)</attr>",xmltext,re.DOTALL) 
      for item in correct_attrs: 
       correct_attribute = "<attr>" + item + "</attr>" 

       xml2 = open(pa + os.sep + "base_metadata_overall.xml") 
       xmltext2 = xml2.read() 
       old_attrs = re.findall("<attr>(.*?)</attr>",xmltext,re.DOTALL) 
       for item2 in old_attrs: 
        old_attribute = "<attr>" + item + "</attr>"    



        old = etree.fromstring(old_attribute) 
        replacement = new.xpath('//attr') 
        for attr in old.xpath('//attr'): 
         attr.getparent().replace(attr, copy.deepcopy(replacement)) 
         print lxml.etree.tostring(old) 

이 작업을 가지고 아래 참조 :

는 여기에 지금까지 무슨이다. 원본에서 대상으로, 나는 다음과 같은 오류, 어떤 제안을받을 수 있습니까?

노드 = replacements.pop()

IndexError가 :

import os, sys, glob, re, copy, lxml, xml.etree.ElementTree as ET 
from lxml import etree 
path = r"C:\\temp\\python\\xml" 
for fn in os.listdir(path): 
filepaths = glob.glob(path + os.sep + fn + os.sep + "*overall.xml") 
for filepath in filepaths: 
     xmlatributes = open(pa + os.sep + "attributes.xml") 
     xmlatributes_txt = xmlatributes.read() 
     xmltarget = open(pa + os.sep + "base_metadata_overall.xml") 
     xmltarget_txt = xmltarget.read() 
     source = lxml.etree.fromstring(xmlatributes_txt) 
     dest = lxml.etree.fromstring(xmltarget_txt)    




     replacements = source.xpath('//attr') 
     replacements.reverse() 


     for attr in dest.xpath('//attr'): 
      node = replacements.pop() 
      attr.getparent().replace(attr, copy.deepcopy(node)) 
     #print lxml.etree.tostring(dest) 
     tree = ET.ElementTree(dest) 
     tree.write (pa + os.sep + "edited_metadata.xml") 
     print fn + "--- sucessfully edited" 

갱신 2011년 5월 16일 는 "IndexError를 해결하기 위해 몇 가지를 재구성 빈 목록에서 팝업 : 빈에서 팝업 목록 "오류가 발생했습니다. "attr"태그의 대체가 항상 1 대 1 대체가되는 것은 아니라는 것을 알았습니다. 예를 들어. 가끔 소스 .xml에 20 개의 attr이 있고 대상 .xml에 25 개의 attr이있는 경우가 있습니다. 이 경우, 일대일 교체가 중단됩니다.

어쨌든 아래에있는 모든 attr을 제거한 다음 소스 attr로 바꾸십시오. 또한 다른 태그 인 "하위 유형"이 있는지 확인합니다.이 태그가 attr 다음에 추가되지만 "세부 사항"태그 안에 추가됩니다.

도와 주신 모든 분들께 다시 한번 감사드립니다.

import os, sys, glob, re, copy, lxml, xml.etree.ElementTree as ET 
from lxml import etree 
path = r"G:\\63D RRC GIS Data\\metadata\\general\\2010_contract" 
#path = r"C:\\temp\python\\xml" 
for fn in os.listdir(path): 
    correct_title = fn.replace ('_', ' ') + " various facilities" 
    correct_fc_name = fn.replace ('_', ' ') 
    filepaths = glob.glob(path + os.sep + fn + os.sep + "*overall.xml") 
    for filepath in filepaths: 
     print "-----" + fn + "-----" 
     (pa, filename) = os.path.split(filepath) 
     xmlatributes = open(pa + os.sep + "attributes.xml") 
     xmlatributes_txt = xmlatributes.read() 
     xmltarget = open(pa + os.sep + "base_metadata_overall.xml") 
     xmltarget_txt = xmltarget.read() 
     source = lxml.etree.fromstring(xmlatributes_txt) 
     dest = lxml.etree.fromstring(xmltarget_txt) 
     replacements = source.xpath('//attr') 
     replacesubtypes = source.xpath('//subtype') 
     subtype_true_f = len(replacesubtypes) 

     attrtag = dest.xpath('//attr') 
     #print len(attrtag) 
     num_realatrs = len(replacements) 
     for n in attrtag: 
      n.getparent().remove(n) 
     print n.tag + " removed" 

     detailedtag = dest.xpath('//detailed') 
     for n2 in detailedtag: 
      pos = 0 
      for realatrs in replacements: 
       n2.insert(pos + 1, realatrs) 
      print "attr's replaced" 
      if subtype_true_f >= 1: 
       #print subtype_true_f 
       for realsubtypes in replacesubtypes: 
        n2.insert(num_realatrs + 1, realsubtypes) 
       print "subtype's replaced" 

     tree = ET.ElementTree(dest) 
     tree.write (pa + os.sep + "base_metadata_overall_v2.xml") 
     print fn + "--- sucessfully edited" 

답변

0

이것은 XSL-T 변환이 만들어진 것처럼 들립니다. 너 그거 해봤 니?

XML 구문 분석 및 조작을위한 Beautiful Soup와 같은 라이브러리도 좋습니다.

+0

, 내가 측정 실행의 -

업데이트 나는 문서 순서 트리 1에서 해당 노드와 tree2 각 <attr>을 대체하도록 변경 시대와 BeautifulSoup는 정규 표현식 솔루션보다 1000 배 느린 것으로 보입니다. 나는 그것이 일반적인 것 인 척하지는 않지만, 그렇습니다. 그러나 그러한 차이는 중요합니다. – eyquem

1

다음은 lxml을 사용하는 예입니다. 정확히 이 아니며 <attr/> 노드를 어떻게 바꿔야 할 지 확신하지만이 예제는 재사용 할 수있는 패턴을 제공해야합니다.

import copy 
import lxml.etree 

xml1 = '''<root><attr><chaos foo="0"/></attr><attr><arena foo="1"/></attr></root>''' 
xml2 = '''<tree><attr><one/></attr><attr><two/></attr></tree>''' 
tree1 = lxml.etree.fromstring(xml1) 
tree2 = lxml.etree.fromstring(xml2) 

# select <attr/> nodes from tree1, will be used to replace corresponding 
# nodes in tree2 
replacements = tree1.xpath('//attr') 
replacements.reverse() 

for attr in tree2.xpath('//attr'): 
    # replace the attr node in tree2 with 'replacement' from tree1 
    node = replacements.pop() 
    attr.getparent().replace(attr, copy.deepcopy(node)) 

print lxml.etree.tostring(tree2) 

이 결과 : 프로그램에

<tree> 
    <attr><chaos foo="0"/></attr> 
    <attr><arena foo="1"/></attr> 
</tree> 
+0

감사합니다. 내 출신에서 더 분명 했어야 했어. 게시하다. 소스 및 대상 XML에는 여러 "attr"속성이 있으며 모두 서로 다른 내용을 포함합니다. 대상에서 모든 "attr"을 삭제하고 원본에서 "attr"을 모두 바꾸고 싶습니다. – dan

+0

나는 orig를 움켜 잡을 수있다. "attr"콘텐트와 소스 "attr"콘텐트가 있지만 대체 방법을 모르겠습니다. ?? – dan

+0

dest attr을 소스 attr로 대체하는 방법은 무엇입니까? 문서 순서대로 바꾸시겠습니까? – samplebias