The*_*mis 6 python xml lxml xml-namespaces
from lxml import etree
element1 = etree.Element('{j:a}a', nsmap={None: 'j:a'})
etree.SubElement(element1, 'b')
element2 = etree.Element('{j:a}a', nsmap={None: 'j:a'})
etree.SubElement(element2, '{j:a}b')
Run Code Online (Sandbox Code Playgroud)
两个元素序列化为相同的
<a xmlns="j:a"><b/></a>
但两个元素的行为不同
element1.find('b')-> 返回元素
element2.find('b')-> 返回无
如果你反过来做
etree.fromstring("<a xmlns="j:a"><b/></a>")
你从 element2 得到表示,所以
element2.find('b')-> 返回无
<b/>这看起来是一致的,因为树中没有无名称空间,因为<b/>继承了默认名称空间<a/>
那么 element1 中表示的目的是什么?它似乎添加了一个无名称空间子元素<b/>并以这种方式运行。但是当序列化时,元素继承自<a>.
如果它无论如何都不序列化,为什么会存在?
xml 标签可以(但不得)具有命名空间。所以即使根节点定义了默认命名空间,子节点也允许没有命名空间,这并不等同于在默认命名空间中。
element1这是你的和element2:element1的子元素没有命名空间之间的区别;element2的子元素位于默认命名空间中,因为在创建它时指定了默认命名空间。如果你试试
element2.find("{j:l}b"))-> 返回 element b,或者更准确地说,返回 element {j:a}b。
所以是的,命名空间很重要。当您使用 lxml 创建元素时,您可以定义没有名称空间的元素:只是不添加它。
现在我不是 lxml 专家,所以这只是我的猜测。问题是,当您序列化元素时,无法区分真正没有命名空间的元素和默认命名空间中的元素,因此它们以相同的方式表示。
因此,序列化一个元素然后再次解析它,无法给出原始结果。例如,如果使用您的element1您执行以下操作:
sel1 = etree.tostring(element1)
element1s = etree.fromstring(sel1)
Run Code Online (Sandbox Code Playgroud)
事实证明element1s不等于element1,因为子元素b现在是 subelement {j:a}b。解析字符串时,没有命名空间的元素将添加到默认命名空间。
现在,我不知道这是有意为之还是一个错误。据我所知,如果 XML 文档声明了默认命名空间,则所有未明确具有不同命名空间的元素都应被视为默认命名空间。当您使用该函数解析 xml 文档时就会发生这种情况fromstring。仅当未声明默认命名空间时,才可以使用“无命名空间”。
因此,在我看来,您的b子元素element1应该“继承”父节点的名称空间,因为父节点使用 定义了默认名称空间nsmap={None: "j:a"}。
但您也可能会被告知,由于您正在使用 lxml 元素构建文档,因此您有责任将每个元素放入正确的命名空间中,这意味着您必须显式添加默认命名空间。
由于在某些情况下 xml 允许没有名称空间的元素,因此当元素没有名称空间时,lxml 不会抱怨。
我认为将默认命名空间自动添加到声明默认命名空间的元素的子元素将是一个很酷的功能,但它并不存在。
| 归档时间: |
|
| 查看次数: |
601 次 |
| 最近记录: |