파이썬을 사용하여 간단한 XML 파일 만들기


161

파이썬으로 간단한 XML 파일을 만들려면 어떻게해야합니까? (라이브러리 현명한)

내가 원하는 XML은 다음과 같습니다.

<root>
 <doc>
     <field1 name="blah">some value1</field1>
     <field2 name="asdfasd">some vlaue2</field2>
 </doc>

</root>

답변:


310

요즘 가장 인기 있고 매우 간단한 옵션은 ElementTree API 이며, Python 2.5 이후 표준 라이브러리에 포함되었습니다.

사용 가능한 옵션은 다음과 같습니다.

  • ElementTree (ElementTree의 기본 순수 Python 구현. 2.5 이후 표준 라이브러리의 일부)
  • cElementTree (ElementTree의 최적화 된 C 구현. 2.5 이후 표준 라이브러리에서도 제공됨)
  • LXML (libxml2 기반. XPath, CSS 선택기 등 ElementTree API의 풍부한 수퍼 세트를 제공함)

다음은 in-stdlib cElementTree를 사용하여 예제 문서를 생성하는 방법에 대한 예입니다.

import xml.etree.cElementTree as ET

root = ET.Element("root")
doc = ET.SubElement(root, "doc")

ET.SubElement(doc, "field1", name="blah").text = "some value1"
ET.SubElement(doc, "field2", name="asdfasd").text = "some vlaue2"

tree = ET.ElementTree(root)
tree.write("filename.xml")

나는 그것을 테스트하고 작동하지만 공백이 중요하지 않다고 가정합니다. "prettyprint"들여 쓰기가 필요한 경우 알려 주시면 어떻게해야하는지 찾아 보겠습니다. (LXML 관련 옵션 일 수 있습니다. stdlib 구현을 많이 사용하지 않습니다)

추가로 읽을 수있는 유용한 링크는 다음과 같습니다.

마지막으로, cElementTree 또는 LXML은 모든 요구 사항에 대해 충분히 빠르지 만 (둘 다 최적화 된 C 코드 임), 모든 마지막 비트를 짜야하는 상황에 처한 경우 벤치 마크 LXML 사이트는 다음을 나타냅니다.

  • LXML이 XML 직렬화 (생성)에서 분명히 승리
  • 적절한 부모 순회를 구현하는 부작용으로 LXML은 cElementTree보다 약간 느리게 구문 분석됩니다.

1
@ Kasper : Mac이 없어서 문제를 복제 할 수 없습니다. 파이썬 버전을 알려 주시면 리눅스에서 복제 할 수 있는지 살펴 보겠습니다.
ssokolow

4
@nonsensickle 당신은 정말로 새로운 질문을하고 모든 사람들이 혜택을받을 수 있도록 나에게 링크를 보냈습니다. 그러나 올바른 방향으로 안내해 드리겠습니다. DOM (Document Object Model) 라이브러리는 항상 인 메모리 모델을 빌드하므로 SAX (Simple API for XML) 구현이 필요합니다. 필자는 SAX 구현을 살펴본 적이 없지만 입력이 아닌 출력에 in-stdlib 를 사용하기위한 자습서 가 있습니다.
ssokolow

1
@YonatanSimson ElementTree 는 인코딩을 지정하는 경우 에만 순종 하는 것처럼 보이기 때문에 정확한 문자열 을 추가하는 방법을 모르겠습니다 xml_declaration=True...하지만 동등한 동작을 얻으려면 다음과 tree.write()같이 호출 하십시오 : tree.write("filename.xml", xml_declaration=True, encoding='utf-8')명시 적으로 지정하는 한 모든 인코딩을 사용할 수 있습니다 하나. ( ascii웹 서버가 올바르게 구성되어 있다고 믿지 않으면 7 비트 ASCII 세트 외부의 모든 유니 코드 문자가 엔티티 인코딩되도록 강제합니다.)
ssokolow

1
수정 vlaue2하려는 다른 사람에게 상기시켜주는 내용 value2: 오타는 원래 질문의 요청 된 XML 출력에 있습니다. 그 변화까지, 오타 여기 사실 입니다 정확한.
ssokolow

3
문서에 따르면 , cElementTreePython 3.3
Stevoisiak

63

lxml이 라이브러리는 호출 된 XML 생성을위한 매우 편리한 구문이 포함되어 E-공장 . 다음은 내가 제시 한 예를 만드는 방법입니다.

#!/usr/bin/python
import lxml.etree
import lxml.builder    

E = lxml.builder.ElementMaker()
ROOT = E.root
DOC = E.doc
FIELD1 = E.field1
FIELD2 = E.field2

the_doc = ROOT(
        DOC(
            FIELD1('some value1', name='blah'),
            FIELD2('some value2', name='asdfasd'),
            )   
        )   

print lxml.etree.tostring(the_doc, pretty_print=True)

산출:

<root>
  <doc>
    <field1 name="blah">some value1</field1>
    <field2 name="asdfasd">some value2</field2>
  </doc>
</root>

또한 이미 만들어진 노드에 추가하는 것을 지원합니다.

the_doc.append(FIELD2('another value again', name='hithere'))

3
태그 이름이 Python 식별자 규칙을 준수하지 않으면을 사용할 수 있습니다 getattr(예 :) getattr(E, "some-tag").
haridsv

나를 위해 인쇄 lxml.etree.tostring이 AttributeError를 일으켰습니다 : 'lxml.etree._Element'객체에 'etree'속성이 없습니다. "lxml"을 시작하지 않고 작동했습니다. 처럼 : etree.tostring (the_doc, pretty_print = True)
kodlan

19

Yattag http://www.yattag.org/ 또는 https://github.com/leforestier/yattag 는 이러한 XML 문서 (및 HTML 문서)를 작성하는 흥미로운 API를 제공합니다.

컨텍스트 관리자with키워드를 사용 하고 있습니다.

from yattag import Doc, indent

doc, tag, text = Doc().tagtext()

with tag('root'):
    with tag('doc'):
        with tag('field1', name='blah'):
            text('some value1')
        with tag('field2', name='asdfasd'):
            text('some value2')

result = indent(
    doc.getvalue(),
    indentation = ' '*4,
    newline = '\r\n'
)

print(result)

그래서 당신은 얻을 것이다 :

<root>
    <doc>
        <field1 name="blah">some value1</field1>
        <field2 name="asdfasd">some value2</field2>
    </doc>
</root>


4

이러한 간단한 XML 구조의 경우 완전한 XML 모듈을 사용하지 않을 수 있습니다. 가장 간단한 구조의 경우 문자열 템플릿을, 좀 더 복잡한 경우에는 Jinja를 고려하십시오. Jinja는 데이터 목록을 반복 처리하여 문서 목록의 내부 XML을 생성 할 수 있습니다. 원시 파이썬 문자열 템플릿에는 조금 까다 롭습니다.

Jinja 예 는 비슷한 질문에 대한대답을 참조하십시오 .

다음은 문자열 템플릿으로 XML을 생성하는 예입니다.

import string
from xml.sax.saxutils import escape

inner_template = string.Template('    <field${id} name="${name}">${value}</field${id}>')

outer_template = string.Template("""<root>
 <doc>
${document_list}
 </doc>
</root>
 """)

data = [
    (1, 'foo', 'The value for the foo document'),
    (2, 'bar', 'The <value> for the <bar> document'),
]

inner_contents = [inner_template.substitute(id=id, name=name, value=escape(value)) for (id, name, value) in data]
result = outer_template.substitute(document_list='\n'.join(inner_contents))
print result

산출:

<root>
 <doc>
    <field1 name="foo">The value for the foo document</field1>
    <field2 name="bar">The &lt;value&gt; for the &lt;bar&gt; document</field2>
 </doc>
</root>

템플릿 방법의 아쉬운 당신의 탈출하지 것입니다 <>무료. 유틸리티를 끌어 와서 그 문제를 해결했습니다.xml.sax


1

방금 bigh_29의 템플릿 메소드를 사용하여 XML 생성기를 작성했습니다 ... 너무 많은 객체가 '길을 잃지 않고'출력을 제어하는 ​​좋은 방법입니다.

태그와 값에 관해서는 두 개의 배열을 사용했습니다. 하나는 출력 xml에서 태그 이름과 위치를 제공하고 다른 하나는 동일한 태그 목록을 가진 매개 변수 파일을 참조했습니다. 그러나 매개 변수 파일에는 데이터를 가져올 해당 입력 (csv) 파일의 위치 번호도 있습니다. 이런 식으로 입력 파일에서 들어오는 데이터의 위치가 변경되면 프로그램은 변경되지 않습니다. 매개 변수 파일의 해당 태그에서 데이터 필드 위치를 동적으로 계산합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.