본문 바로가기
SW 개발/Python

[Tips] Python: XML Parsing 시 multiple elements on top level

by Kibua20 2020. 6. 8.

1. XML 처리 시 "multiple elements on top level" 에러

XML 에서 well-formed 텍스트 아래와 같이 정의할 수 있다. 아래 5) 번째 조건 "루트" Element는 모든 elment를 포함한다" 조건이  맞지 않아서 Parse Error가 발생한 것이다. Python 2.x 버전의 ElementTree에서는 Exceptin없이 처리하나, Python 3.8 버전에서는 Exeption을 발생시킨다. 

1) 문서는 적절히 인코딩된 올바른(legal) 유니코드 문자만을 포함한다. 
2) <나 & 같은 특수 문법 문자 중 어떤 것도, 원래의 마크업 경계 식별 목적 이외의 목적으로 나타나지 않는다.

 3)  엘리먼트의 한계를 정하는 시작 태그, 끝 태그, 빈 엘리먼트 태그들은 모두 올바르게, 빠지거나 중복됨이 없이, 겹쳐진다(nested).
 3) 엘리먼트의 태그는 대소문자를 구분한다; the beginning and end tags must match exactly.
 4) 태그 이름은 다음 문자를 포함할 수 없다 !"#$%&'()*+,/;<=>?@[\]^`{|}~. 또 공백 문자도 포함할 수 없으며, -, ., 또는 숫자로 시작할 수 없다.
 5) 하나의 "루트" 엘리먼트가 다른 모든 엘리먼트를 포함한다.

※ 출처: https://ko.wikipedia.org/wiki/XML

 

XML 파일의 Root Element 가 2개 이상 포함된 경우라면 XML 자체를 수정해야 한다. 하지만 아래와 같이 최상단에 Comment 가 있는 경우 XML 의 문제라 할 수가 없기 때문에 적절하게 예외 처리가 해야 한다.  (※ AOSP로 배포하는 XML 인 경우에는 대부분 XML 최 상단에  Apache 라이센스 문구가 comment 로 저장되어 있다.)

 

<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2019 The Android Open Source Project

     Licensed under the Apache License, Version 2.0 (the "License");
     you may not use this file except in compliance with the License.
     You may obtain a copy of the License at

          http://www.apache.org/licenses/LICENSE-2.0

     Unless required by applicable law or agreed to in writing, software
     distributed under the License is distributed on an "AS IS" BASIS,
     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     See the License for the specific language governing permissions and
     limitations under the License.
-->
<resources>
  <policy name="Testing">
         <item type="string" name="policy_system" />
    </policy>
</resources>

 

수정  1.  Element tree 에서 parsing할 때 comment를  제외하고 처리.  CommentTreeBuilder() Parsing을 먼저 처리해보고, exeption이 발생하면 Comment를 제외하고 처리

try:
    tree = ET.parse('doubleroot.xml',parser=ET.XMLParser(target = CommentedTreeBuilder()))
except:
    tree = ET.parse('doubleroot.xml')

root = tree.getroot()
dump (root)
tree.write('commented_parser.xml',encoding='utf8',xml_declaration=True)  

 

수정 2. CommentedTreeBuilder() 에서 첫 번째 comment는 Skip 한다.

class CommentedTreeBuilder(ET.TreeBuilder):
def __init__(self, *args, **kwargs):
    super(CommentedTreeBuilder, self).__init__(*args, **kwargs)

 def comment(self, data):
    if ( fisrt comment != True):
       self.start(ET.Comment, {})
       self.data(data)
       self.end(ET.Comment)

 

<관련글>

[모바일/Python] - [Tips] Python: XML Parsing 시 multiple elements on top level

[모바일/Python] - [Tips] Python 에서 XML comment 처리 - Sample code 제공

[모바일/Python] - [Tips] XML 에서 예약/특수 문자 처리

[모바일/Android] - Android Studio 4.0 사용하기

[개발환경] - 15. Git 사용하기#2 (bat, git-fuzzy, git-delta)

[모바일/Python] - SyntaxError: Non-ASCII character in file on, but no encoding declared

[모바일/Python] - Python 2.7과 3.8호환성: a bytes-like object is required, not 'str'에러 수정




댓글