Python – XML 활용

Python – XML

XML 이란?

  • XML은 eXtensible Markup Language 의 약어이다.
  • W3C에서 개발 다른 특수한 목적을 갖는 마크업 언어를 만드는데 사용하도록 권장
  • XML은 확장 가능한 마크업 언어를 나타낸다.
  • XML은 HTML과 유사한 마크업 언어이다.
  • XML은 데이터를 저장하고 전송하도록 설계되었습니다.
  • XML 이ㅃ게 보기 : http://xmlgrid.net/

XML Example

<employees>
    <employee>
        <firstName>Joo</firstName>
        <lastName>Duu</lastName>
    </employee>
    <employee>
        <firstName>Koo</firstName>
        <lastName>Kuu</lastName>
    </employee>
    <employee>
        <firstName>Loo</firstName>
        <lastName>Luu</lastName>
    </employee>
</employees>

XML은 단지 태그 과 값을 이루어진 정보이다

XML 과 HMTL 과의 차이

  • XML은 designed to carry data – with focus on what data is (데이터 자체 관점)
  • HTML 은 designed to display data – with focus on how data looks(데이터가 보여질 모양 관점)
  • XML은 태그가 HTML 처럼 미리 정의 되어 있지 않다

XML Tree

  • XML 문서는 root에서 시작해서 ‘leaves’ 가지를 가지는 트리(tree) 구조 이다
<?xml version="1.0" encoding="UTF-8"?>
<bookstore>

  <book category="cooking">
    <title lang="en">Everyday Italian</title>
    <author>Giada De Laurentiis</author>
    <year>2005</year>
    <price>30.00</price>
  </book>

  <book category="children">
    <title lang="en">Harry Potter</title>
    <author>J K. Rowling</author>
    <year>2005</year>
    <price>29.99</price>
  </book>

  <book category="web">
    <title lang="en">XQuery Kick Start</title>
    <author>James McGovern</author>
    <author>Per Bothner</author>
    <author>Kurt Cagle</author>
    <author>James Linn</author>
    <author>Vaidyanathan Nagarajan</author>
    <year>2003</year>
    <price>49.99</price>
  </book>

  <book category="web" cover="paperback">
    <title lang="en">Learning XML</title>
    <author>Erik T. Ray</author>
    <year>2003</year>
    <price>39.95</price>
  </book>

</bookstore>

XML Tree Structure

DOM node tree

XML Tree Structure

  • XML문서는 요소들의 tree로 구성되어 있다.
  • XML트리는 루트 요소(root element)에서 시작 자식 요소들(child elements)로 가지를 친다
  • 모든 요소들은 자식 요소들을 가질 수 있다.
<root>
  <child>
    <subchild>.....</subchild>
  </child>
</root>

XML 문서는 다음과 같이 자신에 대한 정보(The XML prolog)를 선언 할 수 있다

<?xml version="1.0" encoding="UTF-8"?>

XML 문법 규칙

  • XML 문서는은 하나이 Root Element를 가져야 한다
  • The XML prolog 는 맨 처음 문장에 와야 한다.
  • 모든 XML 요소는 닫는 태그(Closing Tag)를 가져야 한다.
  • XML 태그는 대소문자를 구분한다.
  • XML 요소는 정상적으로 중첩되어야 한다.
<b><i>This text is bold and italic</b></i> (X)
<b><i>This text is bold and italic</i></b> (O)
  • XML 속성 값은 반드시 쌍따움표 안데 들어가야 한다.
<note date=12/11/2007>Text</note> (X)
<note date="12/11/2007">Text</note> (O)
  • XML 주석
<!-- This is a comment -->
  • 구문 규칙을 준수하는 XML문서를 Well Formed XML 라 한다.

XML 요소 (XML Element)

XML 요소는 다음을 포함한다
– text
– 속성 attributes
– 다른 요소 other elements

<bookstore>
  <book category="children">
    <title>Harry Potter</title>
    <author>J K. Rowling</author>
    <year>2005</year>
    <price>29.99</price>
  </book>
  <book category="web">
    <title>Learning XML</title>
    <author>Erik T. Ray</author>
    <year>2003</year>
    <price>39.95</price>
  </book>
</bookstore>

빈 XML 요소 (Empty XML Elements)

<element></element> (O)
<element /> (O)

XML 요소 이름 규칙 (XML Naming Rule)

  • 대소문자를 가린다.
  • 첫 글자는 문자여야 한다.
  • 공백이 들어가면 안된다.

Naming Styles (참고)

Style Example Description
Lower case <firstname> All letters lower case
Upper case <FIRSTNAME> All letters upper case
Underscore <first_name> Underscore separates words
Pascal case <FirstName> Uppercase first letter in each word
Camel case <firstName> Uppercase first letter in each word except the first

XML (속성) XML Attributes

  • xml 속성은 특별한 요소와 관련된 데이터를 포함하기 위해 사용한다.
  • xml 속성 값은 항상 "" 또는 '' 안에 넣어야 한다.
<person gender="female">
<person gender='female'>
<gangster name='George "Shotgun" Ziegler'>
<gangster name="George "Shotgun" Ziegler">

XML Elements vs. Attributes

Attributes

<note date="2008-01-10">
  <to>Tove</to>
  <from>Jani</from>
</note>

Elements

<note>
  <date>2008-01-10</date>
  <to>Tove</to>
  <from>Jani</from>
</note>
<note>
  <date>
    <year>2008</year>
    <month>01</month>
    <day>10</day>
  </date>
  <to>Tove</to>
  <from>Jani</from>
</note>

요소를 사용하거나 속성을 사용하는데 특별한 규칙은 없다.

하지만

  • 아래와 같이 속성을 사용하지는 말자!!
  • 구조화 된 문서(트리구조)등을 사용 할 수 없다
<note day="10" month="01" year="2008"
to="Tove" from="Jani" heading="Reminder"
body="Don't forget me this weekend!">
</note>

하지만

  • 특정 요소를 구분할 ID references를 지정시는 사용하자
<messages>
  <note id="501">
    <to>Tove</to>
    <from>Jani</from>
    <heading>Reminder</heading>
    <body>Don't forget me this weekend!</body>
  </note>
  <note id="502">
    <to>Jani</to>
    <from>Tove</from>
    <heading>Re: Reminder</heading>
    <body>I will not</body>
  </note>
</messages>

XML Text 를 JavaScript Object로 변환 하기

JSON Text를 자바 스크립트로 변환하기 위해 DOMParser() 를 사용한다.

파일명 : xmltest.html

<!DOCTYPE html>
<html>
<body>

<p id="demo"></p>

<script>
var parser, xmlDoc;
var text = "<bookstore><book>" +
"<title>Everyday Italian</title>" +
"<author>Giada De Laurentiis</author>" +
"<year>2005</year>" +
"</book></bookstore>";

if (window.DOMParser) {
  // code for modern browser
  parser = new DOMParser();
  xmlDoc = parser.parseFromString(text,"text/xml");
} else {
  // code for old IE browsers
  xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
  xmlDoc.async = false;
  xmlDoc.loadXML(text); 
} 

var title_value = xmlDoc.getElementsByTagName("title")[0].childNodes[0].nodeValue;
//alert(title_value);

document.getElementById("demo").innerHTML =
xmlDoc.getElementsByTagName("title")[0].childNodes[0].nodeValue;
</script>

</body>
</html>

Pyhton XML

xml.etree.ElementTree module 사용

from urllib.request import urlopen
from xml.etree.ElementTree import parse

# Download the RSS feed and parse it
u = urlopen('http://planet.python.org/rss20.xml')
doc = parse(u)

# Extract and output tags of interest
for item in doc.iterfind('channel/item'):
    title = item.findtext('title')
    date = item.findtext('pubDate')
    link = item.findtext('link')

    print(title)
    print(date)
    print(link)
    print()

네이버 OPEN API 로 책 검색기 만들기 – XML

사이트 주소 : https://developers.naver.com

오픈API 이용신청

로그인 > Documents > API 공통 가이드 > 오픈API 이용신청

오픈API 사용방법

https://developers.naver.com/docs/search/book/

파일명 : naver_book_search_xml.py

import urllib.request
from xml.etree.ElementTree import parse

client_id = "****" # 애플리케이션 등록시 발급 받은 값 입력
client_secret = "****" # 애플리케이션 등록시 발급 받은 값 입력
encText = urllib.parse.quote("파이썬")
url = "https://openapi.naver.com/v1/search/book.xml?query=" + encText # xml 결과
request = urllib.request.Request(url)
request.add_header("X-Naver-Client-Id",client_id)
request.add_header("X-Naver-Client-Secret",client_secret)
response = urllib.request.urlopen(request)
rescode = response.getcode()
if(rescode==200):

    resp = parse(response)
    for item in resp.iterfind('channel/item'):
        title = item.findtext('title')
        date = item.findtext('price')
        link = item.findtext('discount')

        print(title)
        print(date)
        print(link)
        print()
else:
    print("Error Code:" + rescode)

urllib 라이브러리 import

  • https://docs.python.org/3/library/urllib.html (파이썬 표준 라이브러리)

  • http 프로토콜 서버에 요청/응답을 할 수 있도록 도와주 라이브러리

  • request는 클라이언트의 요청을 처리

  • response는 서버의 응답을 처리한다.
  • parse는 URL을 분석한다.

request url 생성

  • urllib.parse.quote를 통해서 비 ASCII 문자를 UTF-8 형식으로 URL 인코딩

  • 문자열은 유니코드로 구성되어있고, 바이트는 0~255사이 코드의 열

    foo = '1234abcd'        # 문자열(유니코드)
    koo = b'1234abcd'       # 바이트 상수(b로 시작)
    foo_enc = foo.encode()  # 문자열(유니코드) -> 바이트
    koo_dec = koo.decode()  # 바이트 -> 문자열(유니코드, utf-8)
    
    print(type(foo))        # <class 'str'>
    print(type(koo))        # <class 'bytes'>
    print(type(foo_enc))    # <class 'bytes'>
    print(type(koo_dec))    # <class 'str'>
    
    

Request 객체 생성 및 header 추가

  • urllib.request.Request 클래스는 URL 요청과 관련된 클래
  • http 통신 시 header 값을 설정하거나, HTTP request method(PUT,UPDATE,DELETE..) 등을 설정
  • Request 클래스의 add_header메소드로 헤더 정보를 추가

urlopen(요청) 및 response (응답)

  • urllib.request.urlopen 메소드에 매개변수로 url string 혹은 request 객체를 전달
  • header 정보를 포함시 request 객체로 전달
  • urlopen 메소드는 http.client.HTTPResponse 객체 리턴
  • HTTPResponse 객체 메소드

  • geturl() : source 의 url을 반환(redirect 여부를 확인)

  • getcode() : response의 HTTP status code 를 리턴

오류코드확인 : https://developers.naver.com/docs/search/blog/

response 객체

  • status code가 200인 경우 (정상 호출)
import urllib.request
from xml.etree.ElementTree import parse

def py_xml_proc(data):
    for item in data.iterfind('channel/item'):
        book_title = item.findtext('title')
        book_price = item.findtext('price')
        book_discount = item.findtext('discount')
        book_info = "제목 : {0} / 가격 : {1} / 할인가 : {2}".format(book_title, book_price, book_discount)
        print(book_info)

def naver_search_xml(search_word):
    client_id = "*****"  # 애플리케이션 등록시 발급 받은 값 입력
    client_secret = "*****"  # 애플리케이션 등록시 발급 받은 값 입력
    search_word_enc = urllib.parse.quote(search_word)
    url = "https://openapi.naver.com/v1/search/book.xml?query=" + search_word_enc + "&display=" + book_num + "&sort=count"  # XML 결과
    request = urllib.request.Request(url)
    request.add_header("X-Naver-Client-Id", client_id)
    request.add_header("X-Naver-Client-Secret", client_secret)
    response = urllib.request.urlopen(request)
    rescode = response.getcode()
    if (rescode == 200):
        xml_data = parse(response)
        py_xml_proc(xml_data)
    else:
        print("Error Code:" + rescode)

book_num = "3"
#book_name = "파이썬"
book_name = input("Enter Book Name : ")
naver_search_xml(book_name)

네이버 OPEN API 책 검색기 최종

import urllib.request
from xml.etree.ElementTree import parse

def py_xml_proc(data):
    for item in data.iterfind('channel/item'):
        book_title = item.findtext('title')
        book_price = item.findtext('price')
        book_discount = item.findtext('discount')
        book_info = "제목 : {0} / 가격 : {1} / 할인가 : {2}".format(book_title, book_price, book_discount)
        print(book_info)

def naver_search_xml(search_word):
    client_id = "*****"  # 애플리케이션 등록시 발급 받은 값 입력
    client_secret = "*****"  # 애플리케이션 등록시 발급 받은 값 입력
    search_word_enc = urllib.parse.quote(search_word)
    url = "https://openapi.naver.com/v1/search/book.xml?query=" + search_word_enc + "&display=" + book_num + "&sort=count"  # XML 결과
    request = urllib.request.Request(url)
    request.add_header("X-Naver-Client-Id", client_id)
    request.add_header("X-Naver-Client-Secret", client_secret)
    response = urllib.request.urlopen(request)
    rescode = response.getcode()
    if (rescode == 200):
        xml_data = parse(response)
        py_xml_proc(xml_data)
    else:
        print("Error Code:" + rescode)

book_num = "3"

prompt = """
... 1. Book Search
... 2. Blog Serach
... 3. News Serch
... 4. Quit
...
... Enter number: """
number = 0
while number != 4:
    print(prompt)
    number = int(input())
    if number == 1:
        book_name = input("Enter Book Name : ")
        naver_search_xml(book_name)


답글 남기기

이메일 주소는 공개되지 않습니다. 필수 항목은 *(으)로 표시합니다