1

ElementTree を使用して XML ノードを追加できますが、XML ファイルをテキスト形式で開くと、同じようなツリー構造ではなく、1 行で出力が返されます。minidom.toprettyxml も使用してみましたが、元の XML に出力を追加する方法がわかりません。スクリプトを他の環境でも再現できるようにしたいので、lxml などの外部ライブラリは使用しない方がよいと思います。出力をきれいに印刷する方法を教えてください。- パイソン2.7

サンプル XML。これは、テキスト形式とエクスプローラーの両方でどのように見えるかです。

<?xml version="1.0" encoding="utf-8"?>
<default_locators >
  <locator_ref>
    <name>cherry</name>
    <display_name>cherrycherry</display_name>
    <workspace_properties>
      <factory_progid>Workspace</factory_progid>
      <path>InstallDir</path>
    </workspace_properties>
  </locator_ref>
</default_locators>

テキスト形式とエクスプローラーの両方で期待される出力。

<?xml version="1.0" encoding="utf-8"?>
<default_locators >
  <locator_ref>
    <name>cherry</name>
    <display_name>cherrycherry</display_name>
    <workspace_properties>
      <factory_progid>Workspace</factory_progid>
      <path>InstallDir</path>
    </workspace_properties>
  </locator_ref>
  <locator_ref>
    <name>berry</name>
    <display_name>berryberry</display_name>
    <workspace_properties>
      <factory_progid>Workspace</factory_progid>
      <path>C:\temp\temp</path>
    </workspace_properties>
  </locator_ref>
</default_locators>

私のスクリプト

#coding: cp932

import xml.etree.ElementTree as ET

tree = ET.parse(r"C:\DefaultLocators.xml")
root = tree.getroot()

locator_ref = ET.SubElement(root, "locator_ref")
name = ET.SubElement(locator_ref, "name")
name.text = " berry"
display_name = ET.SubElement(locator_ref, "display_name")
display_name.text = "berryberry"
workspace_properties = ET.SubElement(locator_ref, "workspace_properties")
factory_progid = ET.SubElement(workspace_properties,"factory_progid")
factory_progid.text = "Workspace"
path = ET.SubElement(workspace_properties, "path")
path.text = r"c:\temp\temp"

tree.write(r"C:\DefaultLocators.xml", encoding='utf-8')

返された出力。スクリプトを実行すると、新しいノードが sample.xml ファイルに追加されますが、元の sample.xml ファイルからすべての改行とインデントが削除された 1 行で出力が返されます。少なくとも、sample.xml ファイルをテキスト形式で開くと、このように表示されます。しかし、エクスプローラーで sample.xml ファイルを開くと、問題ないように見えます。改行とインデントは以前と同じように表示されます。スクリプトを実行した後でも、元のツリー構造をテキスト形式で保持するにはどうすればよいですか?

<default_locators>
  <locator_ref>
    <name>cherry</name>
    <display_name>cherrycherry</display_name>
    <workspace_properties>
      <factory_progid>Workspace</factory_progid>
      <path>InstallDir</path>
    </workspace_properties>
  </locator_ref>
<locator_ref><name> berry</name><display_name>berryberry</display_name><workspace_properties><factory_progid>Workspace</factory_progid><path>c:\temp\temp</path></workspace_properties></locator_ref></default_locators>
4

3 に答える 3

2

要素を扱うときは、次のようにすることができます。 element.tail = '\n' すると、1行で記述されます。

于 2013-12-10T07:19:32.773 に答える
0

lxmlライブラリを試してみる必要があると思います。これは、PythonでXMLを解析するための最良の方法です。それはそのようなもののための魔法の議論*pretty_print*を持っています。次に例を示します。

import lxml.etree as etree

root = etree.Element("root")
for rn in range(10):
    etree.SubElement(root, "column_%s" % str(rn)).text = str(rn*rn)
pretty_data = etree.tostring(root, pretty_print=True, encoding = 'utf-8')
print final_data

結果: http: //pastebin.com/y0rkQ78G

于 2013-01-09T15:31:00.363 に答える
0

XML を elementTree に次のように記述します。

import xml.etree.ElementTree as ET


def serialize_xml(write, elem, encoding, qnames, namespaces):
    tag = elem.tag
    text = elem.text
    if tag is ET.Comment:
        write("<!--%s-->" % _encode(text, encoding))
    elif tag is ET.ProcessingInstruction:
        write("<?%s?>" % _encode(text, encoding))
    else:
        tag = qnames[tag]
        if tag is None:
            if text:
                write(_escape_cdata(text, encoding))
            for e in elem:
                serialize_xml(write, e, encoding, qnames, None)
        else:
            write("\n<" + tag) ## '\n' added by namit
            items = elem.items()
            if items or namespaces:
                if namespaces:
                    for v, k in sorted(namespaces.items(),
                                       key=lambda x: x[1]):  # sort on prefix
                        if k:
                            k = ":" + k
                        write(" xmlns%s=\"%s\"" % (
                            k.encode(encoding),
                            _escape_attrib(v, encoding)
                            ))
                for k, v in sorted(items):  # lexical order
                    if isinstance(k, QName):
                        k = k.text
                    if isinstance(v, QName):
                        v = qnames[v.text]
                    else:
                        v = _escape_attrib(v, encoding)
                    write(" %s=\"%s\"" % (qnames[k], v))
            if text or len(elem):
                write(">")
                if text:
                    write(ET._escape_cdata(text, encoding))
                for e in elem:
                    serialize_xml(write, e, encoding, qnames, None)
                write("</" + tag + ">")
            else:
                write(" />")
    if elem.tail:
        write(ET._escape_cdata(elem.tail, encoding))

ET._serialize_xml=serialize_xml

tree = ET.parse(r"samplexml.xml")
root = tree.getroot()

locator_ref = ET.SubElement(root, "locator_ref")
name = ET.SubElement(locator_ref, "name")
name.text = " berry"
display_name = ET.SubElement(locator_ref, "display_name")
display_name.text = "berryberry"
workspace_properties = ET.SubElement(locator_ref, "workspace_properties")
factory_progid = ET.SubElement(workspace_properties,"factory_progid")
factory_progid.text = "WorkspaceFactory"
path = ET.SubElement(workspace_properties, "path")

ins_out=open("samplexml_1.xml",'wb',1000)
ET.ElementTree(locator_ref).write(ins_out,encoding="ASCII")
ins_out.close()

これにより、完全なファイルが 1 行で書き込まれます。xml テールに空白を追加せずに。

于 2013-01-09T05:18:40.410 に答える