파이썬으로 XML 파싱하기 2

이 포스트는 파이썬으로 XML 파싱하기 포스트를 바탕으로 다시 포스팅합니다.

여기서 바뀐 점은 다음과 같습니다.

  • 문자열로부터 직접 XML 문서를 받아들이는 방식
  • .find() 메소드 사용으로 더 간편하게 찾는 방식

코딩해 보면 다음과 같이 됩니다.

xmlstr = """<?xml version="1.0"?>
<girlgroup>
	<name alias="GFRIEND">여자친구</name>
	<members>
		<member>소원</member>
		<member>예린</member>
		<member>은하</member>
		<member>유주</member>
		<member>신비</member>
		<member>엄지</member>
	</members>
	<albums>
		<album order="EP 1집">Season of Glass</album>
		<album order="EP 2집">Flower Bud</album>
		<album order="EP 3집">Snowflake</album>
		<album order="정규 1집">LOL</album>
		<album order="EP 4집">THE AWAKENING</album>
	</albums>
</girlgroup>
"""

위와 같이 XML 문서를 저장해 놓은 문자열이 있다고 했을 때

from lxml import etree

# Empty array
members = []
albums = []

# Load XML
root = etree.fromstring(xmlstr)

gname = root.find("name").text
for x_member in root.find("members"):
	members.append(x_member.text)
for x_album in root.find("albums"):
	albums.append([x_album.get("order"), x_album.text])
	
# Print
print("걸그룹 %s에 대한 정보는 다음과 같습니다:" % gname, end="\n\n")
 
print(" 멤버: ", end="")
print(", ".join(members))
 
print("\n [앨범 목록]")
for album in albums:
	print("  * %s: %s" % (album[0], album[1]) )

이렇게 코딩합니다. 기본적으로는 파이썬으로 XML 파싱하기 포스트와 같지만 차이가 있습니다.

우선, 28번 줄에서 XML을 받아들이는데 파일이 아닌 문자열로 받아들입니다. 이 때는 etree.parse() 대신 etree.fromstring() 메소드를 사용합니다. 이 경우 .getroot() 메소드를 거치지 않고 바로 루트 요소로 변환됩니다.

30번 줄은 하위 요소들을 살피면서 .tag 프로퍼티로 태그 이름을 찾지 않고 그 대신 .find() 메소드를 써서 태그 이름을 찾습니다. 그룹 이름이 적혀 있는 <name> 태그를 찾아 그 뒤에 .text 프로퍼티를 써서 태그 안의 텍스트를 변환합니다.

31번 줄과 33번 줄도 같은 방식입니다. 다만 find 메소드 뒤에 아무 프로퍼티도 쓰지 않으면 그 태그 밑의 요소들을 배열 형식으로 돌려주게 됩니다.

그 다음은 파이썬으로 XML 파싱하기 포스트와 같습니다.

걸그룹 여자친구에 대한 정보는 다음과 같습니다:

 멤버: 소원, 예린, 은하, 유주, 신비, 엄지

 [앨범 목록]
  * EP 1집: Season of Glass
  * EP 2집: Flower Bud
  * EP 3집: Snowflake
  * 정규 1집: LOL
  * EP 4집: THE AWAKENING

이와 같이 됩니다.

참고사항

  • .find() 메소드는 해당 태그의 바로 아랫 단계에 있는 태그만 찾아집니다.
    이 예제에서는 root.find("member") 형식으로 찾으면 <members> 밑의 <member> 태그가 탐색되지 않으므로 members = root.find("members") | member.find("member") 또는 root.find("members").find("member")처럼 한 다리 거쳐가는 방식을 사용해야 합니다.
  • .find() 메소드를 쓰면 해당 이름을 가진 태그가 둘 이상일 경우 그 중 첫 번째 태그만 탐색됩니다. 예를 들어, 바로 위처럼 root.find("members").find("member").text 코드를 쓸 경우 맨 첫 번째 <member> 태그에 있는 ‘소원’이라는 값이 추출됩니다.
  • 만약 같은 이름의 태그가 있을 때 맨 첫 번째 태그만이 아니라 그 이름의 모든 태그를 배열로 추출하고자 할 때는 .findall() 메소드를 씁니다. 예를 들어, root.find("members").findall("member")[1].text 코드를 쓸 경우 <member> 태그가 배열화되어 그 중 두 번째 태그에 있는 ‘예린’이라는 값이 추출됩니다.

답글 남기기

이메일 주소는 공개되지 않습니다.