복붙노트

[PYTHON] Python과 minidom을 사용한 XML 구문 분석

PYTHON

Python과 minidom을 사용한 XML 구문 분석

Python (minidom)을 사용하여 XML 파일을 구문 분석하여 다음과 같은 계층 구조를 인쇄합니다. 여기서 들여 쓰기는 중요한 계층 관계를 보여주기 위해 사용됩니다.

My Document
Overview
    Basic Features
    About This Software
        Platforms Supported

대신, 프로그램은 노드를 통해 여러 번 반복하고 다음을 생성하여 중복 노드를 인쇄합니다. (각 반복마다 노드 목록을 보면 왜 이렇게되는지 분명하지만 원하는 노드 목록을 얻을 수있는 방법을 찾지 못하는 것 같습니다.)

My Document
Overview
Basic Features
About This Software
Platforms Supported
Basic Features
About This Software
Platforms Supported
Platforms Supported

다음은 XML 소스 파일입니다.

<?xml version="1.0" encoding="UTF-8"?>
<DOCMAP>
    <Topic Target="ALL">
        <Title>My Document</Title>
    </Topic>
    <Topic Target="ALL">
        <Title>Overview</Title>
        <Topic Target="ALL">
            <Title>Basic Features</Title>
        </Topic>
        <Topic Target="ALL">
            <Title>About This Software</Title>
            <Topic Target="ALL">
                <Title>Platforms Supported</Title>
            </Topic>
        </Topic>
    </Topic>
</DOCMAP>

다음은 Python 프로그램입니다.

import xml.dom.minidom
from xml.dom.minidom import Node

dom = xml.dom.minidom.parse("test.xml")
Topic=dom.getElementsByTagName('Topic')
i = 0
for node in Topic:
    alist=node.getElementsByTagName('Title')
    for a in alist:
        Title= a.firstChild.data
        print Title

하위 토픽 이름을 'SubTopic1'및 'SubTopic2'와 같은 것으로 변경하여 'Topic'요소를 중첩하지 않아도 문제를 해결할 수있었습니다. 그러나 다른 요소 이름을 사용하지 않고 내장 된 XML 계층 적 구조화를 활용하고 싶습니다. 'Topic'요소를 중첩 할 수 있어야하며 현재보고있는 수준의 'Topic'수준을 알아야합니다.

나는 많은 성공을 거두지 않고 여러 가지 다른 XPath 함수를 시도했다.

해결법

  1. ==============================

    1.getElementsByTagName은 재귀 적이며 tagName이 일치하는 모든 자손을 가져옵니다. 주제에는 제목이있는 다른 주제가 포함되어 있기 때문에 호출은 하향식 제목을 여러 번 가져옵니다.

    getElementsByTagName은 재귀 적이며 tagName이 일치하는 모든 자손을 가져옵니다. 주제에는 제목이있는 다른 주제가 포함되어 있기 때문에 호출은 하향식 제목을 여러 번 가져옵니다.

    일치하는 모든 하위 항목에 대해서만 요청하고 XPath를 사용할 수없는 경우 간단한 필터를 작성할 수 있습니다 (예 :

    def getChildrenByTagName(node, tagName):
        for child in node.childNodes:
            if child.nodeType==child.ELEMENT_NODE and (tagName=='*' or child.tagName==tagName):
                yield child
    
    for topic in document.getElementsByTagName('Topic'):
        title= list(getChildrenByTagName('Title'))[0]         # or just get(...).next()
        print title.firstChild.data
    
  2. ==============================

    2.그 코멘트를 여기에 두자.

    그 코멘트를 여기에 두자.

    시도해 줘서 고마워. 그것은 효과가 없었지만 아이디어가있었습니다. 다음 작품들 (동일한 일반적인 생각 : FWIW, nodeType은 ELEMENT_NODE 임) :

    import xml.dom.minidom
    from xml.dom.minidom import Node
    
    dom = xml.dom.minidom.parse("docmap.xml")
    
    def getChildrenByTitle(node):
        for child in node.childNodes:
            if child.localName=='Title':
                yield child
    
    Topic=dom.getElementsByTagName('Topic')
    for node in Topic:
        alist=getChildrenByTitle(node)
        for a in alist:
    #        Title= a.firstChild.data
            Title= a.childNodes[0].nodeValue
            print Title
    
  3. ==============================

    3.다음 생성기를 사용하여 목록을 실행하고 들여 쓰기 수준의 제목을 얻을 수 있습니다.

    다음 생성기를 사용하여 목록을 실행하고 들여 쓰기 수준의 제목을 얻을 수 있습니다.

    def f(elem, level=-1):
        if elem.nodeName == "Title":
            yield elem.childNodes[0].nodeValue, level
        elif elem.nodeType == elem.ELEMENT_NODE:
            for child in elem.childNodes:
                for e, l in f(child, level + 1):
                    yield e, l
    

    파일로 테스트하는 경우 :

    import xml.dom.minidom as minidom
    doc = minidom.parse("test.xml")
    list(f(doc))
    

    당신은 다음 튜플들로 목록을 얻을 것입니다 :

    (u'My Document', 1), 
    (u'Overview', 1), 
    (u'Basic Features', 2), 
    (u'About This Software', 2), 
    (u'Platforms Supported', 3)
    

    물론 미세 조정이되는 것은 기본적인 아이디어 일뿐입니다. 시작 부분에 공백이 있으면 생성기에서 바로 공백을 지정할 수 있지만 더 유연하게 지정할 수 있습니다. 자동으로 첫 번째 레벨을 감지 할 수도 있습니다 (여기에 레벨을 -1로 초기화하는 것은 좋지 않습니다).

  4. ==============================

    4.그게 도움이 될 것 같아.

    그게 도움이 될 것 같아.

    import os
    import sys
    import subprocess
    import base64,xml.dom.minidom
    from xml.dom.minidom import Node
    f = open("file.xml",'r')
    data = f.read()
    i = 0
    doc = xml.dom.minidom.parseString(data)
    for topic in doc.getElementsByTagName('Topic'):
       title= doc.getElementsByTagName('Title')[i].firstChild.nodeValue
       print title
       i +=1
    

    산출:

    My Document
    Overview
    Basic Features
    About This Software
    Platforms Supported
    
  5. ==============================

    5.재귀 함수 :

    재귀 함수 :

    import xml.dom.minidom
    
    def traverseTree(document, depth=0):
      tag = document.tagName
      for child in document.childNodes:
        if child.nodeType == child.TEXT_NODE:
          if document.tagName == 'Title':
            print depth*'    ', child.data
        if child.nodeType == xml.dom.Node.ELEMENT_NODE:
          traverseTree(child, depth+1)
    
    filename = 'sample.xml'
    dom = xml.dom.minidom.parse(filename)
    traverseTree(dom.documentElement)
    

    귀하의 XML :

    <?xml version="1.0" encoding="UTF-8"?>
    <DOCMAP>
        <Topic Target="ALL">
            <Title>My Document</Title>
        </Topic>
        <Topic Target="ALL">
            <Title>Overview</Title>
            <Topic Target="ALL">
                <Title>Basic Features</Title>
            </Topic>
            <Topic Target="ALL">
                <Title>About This Software</Title>
                <Topic Target="ALL">
                    <Title>Platforms Supported</Title>
                </Topic>
            </Topic>
        </Topic>
    </DOCMAP>
    

    원하는 출력 :

     $ python parse_sample.py 
          My Document
          Overview
              Basic Features
              About This Software
                  Platforms Supported
    
  6. from https://stackoverflow.com/questions/1596829/xml-parsing-with-python-and-minidom by cc-by-sa and MIT license