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階層構造を利用したいと思います。 「トピック」要素をネストできるようになり、どのトピック「トピック」が現在見ているかを知る方法がいくつかあるはずです。
私は多くの異なるXPath関数を試しましたが、あまり成功していません。
getElementsByTagNameは再帰的で、一致するtagNameを持つallの子孫を取得します。トピックには、タイトルもある他のトピックが含まれているため、呼び出しは下位のタイトルを何度も取得します。
一致するすべての直接の子のみを要求する場合で、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
ここにそのコメントを載せましょう...
試みをありがとう。それはうまくいきませんでしたが、いくつかのアイデアを与えてくれました。次の作品(同じ一般的なアイデア; 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
それは助けになると思います
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
次のジェネレータを使用してリストを実行し、インデントレベルのタイトルを取得できます。
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に初期化するのはお粗末です...)。
再帰関数:
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