파싱할 xml은 다음과 같습니다.
ml_string = '''<?xml version="1.0"?>
<data>
<tool name="Keras">
<rank>1</rank>
<content>good</content>
<merge name="TensorFlow" year="2020"/>
</tool>
<tool name="TensorFlow">
<rank>1</rank>
<content>nice</content>
</tool>
<tool2 name="PyTorch">
<rank>2</rank>
<content>research</content>
</tool2>
<tool2 name="MXNet">
<rank>3</rank>
<content>well</content>
</tool2>
</data>
'''
ElementTree를 통해 xml 파일을 지정하고 root에 접근하는 방법은 다음과 같습니다.
tree = elemTree.parse('ml.xml')
root = tree.getroot()
* 여기서는 예제를 위해 string을 사용하므로 다음을 사용합니다. 파일을 통한 파싱은 위 코드로 해야합니다.
아래 코드는 관련 없습니다.
root = ET.fromstring(ml_string)
태그와 태그가 가지고 있는 속성은 다음과 같이 확인할 수 있습니다.
print(root.tag, root.attrib)
- data {}
ElementTree에서는 대표적으로 find(), findall(), iter() 함수를 많이 사용합니다.
find()
print(root.find('tool'))
print(root.find('tool').tag, '|', root.find('tool').attrib)
# 하위 태그를 탐색할 수 있습니다.
for child in root.find('tool'):
print(child.tag, child.attrib)
- <Element 'tool' at 0x000001E489FB5AE8>
tool | {'name': 'Keras'}
rank {}
content {}
merge {'name': 'TensorFlow', 'year': '2020'} - root.find('tag_name')은 여러 개의 태그 중에서 가장 첫 번째 태그를 가져옵니다.
- for-loop를 통해 하위 태그를 확인하고 있습니다.
findall()
print(root.findall('tool'))
# <tool/> 태그를 전부 탐색할 수 있습니다.
for root_e in root.findall('tool'):
print(root_e.tag, root_e.attrib)
- [<Element 'tool' at 0x000001E489FB5AE8>, <Element 'tool' at 0x000001E489FBE228>]
tool {'name': 'Keras'}
tool {'name': 'TensorFlow'} - 원하는 태그를 전부 찾아서 리스트 형태로 얻을 수 있습니다. 하지만 하위 태그는 찾아주지 않습니다.
iter()
# <tool2/> 태그를 전부 탐색할 수 있습니다.
for root_e in root.iter('tool2'):
print(root_e.tag, root_e.attrib)
- tool2 {'name': 'PyTorch'}
tool2 {'name': 'MXNet'} - find, findall과 다르게 상위 또는 하위 태그를 전부 찾아줍니다.
다음은 원하는 두 가지 태그를 찾고, 태그의 text를 변경하여 저장하는 것까지의 예제 코드입니다.
def parse_xml(xml_list):
for xml_name in xml_list:
xml = './' + xml_name
attached_name = 'abc'
tree = elemTree.parse(gml)
root = tree.getroot()
# 두 개 태그의 text를 수정한다고 가정합니다.
for attr1, attr2 in zip(root.iter('attr_1'), root.iter('attr_2')):
attr1_newtext = attached_name + attr1.text
attr2_newtext = attached_name + attr2.text
attr1.text = attr1_newtext
attr2.text = attr2_newtext
# 수정한 xml 파일을 저장합니다.
tree.write('./' + xml_name)
파싱할 xml에 namespace가 존재하는 경우
간혹 xml에 다음과 같이 namespace가 존재하는 경우가 있다.
- xmlns:app="http://www.opengis.net/citygml/appearance/2.0"
- xmlns:bldg="http://www.opengis.net/citygml/building/2.0"
- xmlns:core="http://www.opengis.net/citygml/2.0"
- xmlns:gml="http://www.opengis.net/gml"
다음과 같이 namespace를 등록하지 않으면, ElementTree가 자동으로 ns0, ns1, ...으로 등록하기 때문에 주의해야 한다.
ET.register_namespace("gml", "http://www.opengis.net/gml")
ET.register_namespace("bldg", "http://www.opengis.net/citygml/building/2.0")
ET.register_namespace("app", "http://www.opengis.net/citygml/appearance/2.0")
ET.register_namespace("core", "http://www.opengis.net/citygml/2.0")
'# 기타 공부한 것들 > 파이썬_etc.' 카테고리의 다른 글
for-loop로 간단한 maxpooling, convolution 만들어보기 (0) | 2020.03.24 |
---|---|
파일 이름 변경하기 (0) | 2020.03.20 |
np.patition, np.argpatition에 대해서 (0) | 2019.09.24 |
glob, 디렉토리 안의 특정 확장자 찾기 (0) | 2019.08.23 |
데이터 분석 시 쓰이는 plot(코드x, plot별 메소드 이름) (0) | 2019.07.23 |