2014-11-06 2 views
0

병합하려고하는 두 개의 XML 파일이 있습니다. 이전의 다른 질문을 살펴 보았지만 문제를 해결할 수있는 느낌이 들지 않습니다. 내 상황이 고유하다고 생각하는 것은 속성 값을 기준으로 요소를 찾은 다음 반대 파일에 병합해야한다는 것입니다.요소를 특성 값별로 일치시켜 두 개의 XML 파일을 병합합니다.

두 개의 파일이 있습니다. 하나는 영어 번역 카탈로그이고 두 번째는 일본어 번역 카탈로그입니다. 아래를 참조하십시오.

아래 코드에서 XML에 MessageCatalogueEntry, MessageCatalogueFormEntry 및 MessageCatalogueFormItemEntry와 같은 자식을 병합 할 세 가지 요소가 있음을 알 수 있습니다. 나는 수백 개의 파일을 가지고 있고 각 파일에는 수천 개의 줄이있다. 앞서 나열한 세 가지 요소보다 더 많은 요소가있을 수 있지만 모든 요소에 "핵심"특성이 있는지 확인합니다.

내 계획 :

  • 파일 1을 반복 처리하고 "키"속성의 모든 값의 목록을 만들 수 있습니다. 이 예에서
    • , 목록 key_values = [321, 260, 320]
  • 다음, 나는 하나를 사용하여 key_value 목록 하나를 통해 갈거야 것입니다.
  • 속성이 key=321 인 요소에 대해 파일 1을 검색합니다.
  • 다음 파일에서 key=321와 요소의 아이를 잡아 1.
  • 다음, 파일 2에서 key=321를 가진 요소를 찾아 내가 이전에 내가거야 1.
  • 다음 파일에서 잡고 자식 요소를 추가 key_values 목록을 통해 동일한 프로세스 루핑을 반복하십시오.
  • 다음으로 utf8 인코딩을 유지하는 파일에 새 xml 루트를 씁니다.

파일 1 :

<?xml version="1.0" encoding="utf-8"?> 
<!DOCTYPE MessageCatalogue []> 
<PackageEntry> 
    <MessageCatalogue designNotes="Undefined" isPrivate="false" lastKey="362" name="AddKMRichSearchEngineAdmin_AutoTranslationCatalogue" nested="false" version="3.12.0"> 
     <MessageCatalogueEntry key="321"> 
     <MessageCatalogueEntry_loc locale="" message="active"/> 
     </MessageCatalogueEntry> 
     <MessageCatalogueFormEntry key="260"> 
     <MessageCatalogueFormEntry_loc locale="" shortTitle="Configuration" title="Spider Configuration"/> 
     </MessageCatalogueFormEntry> 
     <MessageCatalogueFormItemEntry key="320"> 
     <MessageCatalogueFormItemEntry_loc hintText="" label="Manage Recognised Phrases" locale="" mnemonic="" scriptText=""/> 
     </MessageCatalogueFormItemEntry> 
    </MessageCatalogue> 
    </PackageEntry> 

파일 2 :

<?xml version="1.0" encoding="utf-8"?> 
<!DOCTYPE MessageCatalogue[]> 
<PackageEntry> 
    <MessageCatalogue designNotes="Undefined" isPrivate="false" lastKey="362" name="" nested="false" version="3.12.0"> 
    <MessageCatalogueEntry key="321"> 
     <MessageCatalogueEntry_loc locale="ja" message="アクティブ" /> 
    </MessageCatalogueEntry> 
    <MessageCatalogueFormEntry key="260"> 
     <MessageCatalogueFormEntry_loc locale="ja" shortTitle="設定" title="Spider Configuration/スパイダー設定" /> 
    </MessageCatalogueFormEntry> 
    <MessageCatalogueFormItemEntry key="320"> 
     <MessageCatalogueFormItemEntry_loc hintText="" label="認識されたフレーズを管理" locale="ja" mnemonic="" scriptText="" /> 
    </MessageCatalogueFormItemEntry> 
    </MessageCatalogue> 
</PackageEntry> 

출력 : 나는 문제가 단지에도 신경 쓸 요소를 잡아 키를 잡는 데

<?xml version="1.0" encoding="utf-8"?> 
<!DOCTYPE MessageCatalogue []> 
<PackageEntry> 
    <MessageCatalogue designNotes="Undefined" isPrivate="false" lastKey="362" name="AddKMRichSearchEngineAdmin_AutoTranslationCatalogue" nested="false" version="3.12.0"> 
     <MessageCatalogueEntry key="321"> 
     <MessageCatalogueEntry_loc locale="" message="active"/> 
     <MessageCatalogueEntry_loc locale="ja" message="アクティブ" /> 
     </MessageCatalogueEntry> 
     <MessageCatalogueFormEntry key="260"> 
     <MessageCatalogueFormEntry_loc locale="" shortTitle="Configuration" title="Spider Configuration"/> 
     <MessageCatalogueFormEntry_loc locale="ja" shortTitle="設定" title="Spider Configuration/スパイダー設定" /> 
     </MessageCatalogueFormEntry> 
     <MessageCatalogueFormItemEntry key="320"> 
     <MessageCatalogueFormItemEntry_loc hintText="" label="Manage Recognised Phrases" locale="" mnemonic="" scriptText=""/> 
     <MessageCatalogueFormItemEntry_loc hintText="" label="認識されたフレーズを管理" locale="ja" mnemonic="" scriptText="" /> 
     </MessageCatalogueFormItemEntry> 
    </MessageCatalogue> 
    </PackageEntry> 

값. 예를 들어, 나는 elementtree 라이브러리와 함께 연주 봤는데 난 그냥 MessageCatalogueEntry을 얻을 수 있었으면이 코드를 작성하지만, 난 단지 자녀를 받고 있어요 :

from xml.etree import ElementTree as et 

tree_japanese = et.parse('C:\\blah\\blah\\blah\\AddKMRichSearchEngineAdmin_AutoTranslationCatalogue_JA.xml') 
root_japanese = tree_japanese.getroot() 
MC_japanese = root_japanese.findall("MessageCatalogue") 

for x in MC_japanese: 
    messageCatalogueEntry = x.findall("MessageCatalogueEntry") 
    for m in messageCatalogueEntry: 
     print et.tostring(m[0], encoding='utf8') 

tree_english = et.parse('C:\\blah\\blah\\blah\\AddKMRichSearchEngineAdmin\\AddKMRichSearchEngineAdmin_AutoTranslationCatalogue.xml') 
root_english = tree_english.getroot() 
MC_english = root_english.findall("MessageCatalogue") 

for x in MC_english: 
    messageCatalogueEntry = x.findall("MessageCatalogueEntry") 
    for m in messageCatalogueEntry: 
     print et.tostring(m[0], encoding='utf8') 

어떤 도움을 주시면 감사하겠습니다. 나는 지금 몇 일 동안이 일을 해왔고, 처음 시작했을 때보 다 마무리에 더 가깝지 않습니다!

답변

2

실제로 MessageCatalogEntry가 표시됩니다. 문제는 print 문에 있습니다. 요소는 목록처럼 작동하므로 m[0]이 MessageCatalogEntry의 첫 번째 하위 항목입니다. In

messageCatalogueEntry = x.findall("MessageCatalogueEntry") 
for m in messageCatalogueEntry: 
    print et.tostring(m[0], encoding='utf8') 

오른쪽 요소를 보려면 인쇄를 print et.tostring(m, encoding='utf8')으로 변경하십시오.

저는 개인적으로 lxml을 elementtree보다 선호합니다. 항목을 'key'속성으로 연결하려는 경우 xpath를 사용하여 문서 중 하나를 색인화 한 다음 다른 doc으로 가져올 수 있습니다.

import lxml.etree 

tree_english = lxml.etree.parse('english.xml') 
tree_japanese = lxml.etree.parse('japanese.xml') 

# index the japanese catalog 
j_index = {} 
for catalog in tree_japanese.xpath('MessageCatalogue/*[@key]'): 
    j_index[catalog.get('key')] = catalog 

# find catalog entries in english and merge the japanese 
for catalog in tree_english.xpath('MessageCatalogue/*[@key]'): 
    j_catalog = j_index.get(catalog.get('key')) 
    if j_catalog is not None: 
     print 'found match' 
     for child in j_catalog: 
      print 'add one' 
      catalog.append(child) 

print lxml.etree.tostring(tree_english, pretty_print=True, encoding='utf8') 
+0

감사합니다. 이것은 내가 필요한만큼 정확하게 작동합니다. 도와 주셔서 정말 고맙습니다. 나는 너를 업신 여긴하지만 나는 명성이 충분하지 못하다. 나는 자격을 얻었을 때 돌아와서 그렇게 할 것입니다.
내가 궁금한 점 중 하나는 올바른 용어 인 경우 필자의 헤더 (아래 참조)가 쓰여지지 않는다는 것입니다. 그게 큰 문제는 아니지만, 필자는 머리글이 내가 작업하고있는 모든 파일에서 동일하기 때문에 파일에 문자열을 씁니다. 다시 한번 감사드립니다! – alfonso

+0

예, lxml은 헤더를 사용자가 직접 출력 할 것으로 예상합니다. 나는 모든 세부 사항을 기억하지 않는다. – tdelaney

+0

구문 분석 할 다른 방법을 알고 있다면 궁금해하던가요? 아래의 코드는 필요한 CDATA 태그를 제거합니다 : tree_english = lxml.etree.parse ('english.xml'). 내가 documenation을 확인하고 분명히 당신은 CDATA 태그를 유지할 수 있지만 그들이 같은 방법을 사용하여 구문 분석하지 않는 것 같습니다. 여기에 문서가 있습니다. http://lxml.de/2.1/api.html – alfonso

관련 문제