在这个问题中使用"bad in XML"这个短语一直是争论的焦点,所以我想首先在这个上下文中提供一个非常明确的术语定义:如果支持标准XML API很差,迫使一个人使用特定于语言的API,其中命名空间似乎是事后的想法,然后我倾向于将该语言描述为不像其他主流语言那样使用XML.这些问题."糟糕的XML"只是这些条件的简写,我认为这是一种表征它的公平方式.正如我将要描述的那样,我对Python的初步经验引起了对它是否满足这些条件的担忧; 但是,因为一般来说我对Python的经验非常积极,所以我似乎错过了一些东西,
我正在尝试使用Python进行一些非常简单的XML处理.我最初希望能够重用我对标准W3C DOM API的知识,并且很高兴地发现xml.dom和xml.dom.minidom模块在支持这些API方面做得很好.不幸的是,由于以下原因,序列化被证明是有问题的:
我在这里查看了其他类似W3C的库列表:
http://wiki.python.org/moin/PythonXml#W3CDOM-likelibraries
我发现许多其他库,例如4Suite和libxml2dom,也没有得到维护.
另一方面,乍一看似乎维护了itools,但似乎没有可用的Ubuntu/Debian软件包,因此难以部署和维护.
在这一点上,似乎尝试在我的Python应用程序中使用W3C DOM API将是死路一条,我开始关注ElementTree API.但是,我认为eTree API支持名称空间的方式非常难看,每次创建特定名称空间中的元素时都需要使用字符串连接:
http://lxml.de/tutorial.html#namespaces
所以,我的问题是,我忽略了什么,或者支持XML(特别是W3C DOM)在Python中实际上非常糟糕?
下面是一个更精确的问题列表,其中的答案对我有用:
xml.dom
,你使用eg etree
代替W3C DOM吗?我想说 python 处理 XML 得很好。可用的不同库的数量说明了这一点 - 您有很多选择。如果您想要使用的库中缺少某些功能,请随时贡献一些补丁!
我个人使用 DOM 和 lxml.etree(etree 非常快)。然而,我感受到你对命名空间的痛苦。我编写了一个快速帮助函数来处理它:
DEFAULT_NS = "http://www.domain.org/path/to/xml"
def add_xml_namespace(path, namespace=DEFAULT_NS):
"""Adds namespaces to an XPath-ish expression path for etree
Test simple expression:
>>> add_xml_namespace('image/namingData/fileBaseName')
'{http://www.domain.org/path/to/xml}image/{http://www.domain.org/path/to/xml}namingData/{http://www.domain.org/path/to/xml}fileBaseName'
More complicated expression
>>> add_xml_namespace('.//image/*')
'.//{http://www.domain.org/path/to/xml}image/*'
>>> add_xml_namespace('.//image/text()')
'.//{http://www.domain.org/path/to/xml}image/text()'
"""
pattern = re.compile(r'^[A-Za-z0-9-]+$')
tags = path.split('/')
for i in xrange(len(tags)):
if pattern.match(tags[i]):
tags[i] = "{%s}%s" % (namespace, tags[i])
return '/'.join(tags)
Run Code Online (Sandbox Code Playgroud)
我这样使用它:
from lxml import etree
from utilities import add_xml_namespace as ns
tree = etree.parse('file.xml')
node = tree.get_root().find(ns('root/group/subgroup'))
# etc.
Run Code Online (Sandbox Code Playgroud)
如果您事先不知道名称空间,可以从根节点中提取它:
tree = etree.parse('file.xml')
root = tree.getroot().tag
namespace = root[1:root.index('}')]
ns = lambda path: add_xml_namespace(path, namespace)
...
Run Code Online (Sandbox Code Playgroud)
补充说明:这里涉及到一些工作,但是处理 XML 时工作是必要的。这不是 python 问题,而是 XML 问题。