使用lxml保留子元素命名空间序列化
我有几个不同的XML文档,想用lxml把它们合并成一个。问题是,我需要合并后的结果能保留每个子文档根节点的命名空间。lxml似乎会把使用超过一次的命名空间声明推到新文档的根部,这在我的应用中会出问题(这是一个已知的bug)。
举个例子,我有文档A:
<dc xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.openarchives.org/OAI/2.0/oai_dc/">
<title>La difesa della razza: scienza, documentazione, polemica. anno 1:n. 1</title>
</dc>
还有文档B:
<mods xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.loc.gov/mods/v3 http://www.loc.gov/standards/mods/v3/mods-3-3.xsd">
<titleInfo>
<nonSort>La</nonSort>
<title>difesa della razza</title>
<subTitle>scienza, documentazione, polemica</subTitle>
<partNumber>anno 1:n. 1</partNumber>
</titleInfo>
</mods>
我想把它们放在一个元素里,并且这个元素也要使用一个xsi:schemaLocation,但我需要命名空间声明(xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance")出现在所有三个节点中,像这样:
<wrap xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.example.org" xmlns:dc="http://www.foo.org" xmlns:mods="http://www.bar.org">
<dc:dc xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.openarchives.org/OAI/2.0/oai_dc/">
<dc:title>La difesa della razza: scienza, documentazione, polemica. anno 1:n. 1</dc:title>
</dc:dc>
<mods:mods xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.loc.gov/mods/v3 http://www.loc.gov/standards/mods/v3/mods-3-3.xsd">
<mods:titleInfo>
<mods:nonSort>La</mods:nonSort>
<mods:title>difesa della razza</mods:title>
<mods:subTitle>scienza, documentazione, polemica</mods:subTitle>
<mods:partNumber>anno 1:n. 1</mods:partNumber>
</mods:titleInfo>
</mods:mods>
</wrap>
但是,当我用Python/lxml把这两个文档合并时,
wrap.append(dc)
wrap.append(mods)
我发现声明被推到了使用它的最高级节点上。不幸的是,这对我的应用来说是个问题。像这样:
<wrap xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.example.org" xmlns:dc="http://www.foo.org" xmlns:mods="http://www.bar.org">
<dc:dc xsi:schemaLocation="http://www.openarchives.org/OAI/2.0/oai_dc/">
<dc:title>La difesa della razza: scienza, documentazione, polemica. anno 1:n. 1</dc:title>
</dc:dc>
<mods:mods xsi:schemaLocation="http://www.loc.gov/mods/v3 http://www.loc.gov/standards/mods/v3/mods-3-3.xsd">
<mods:titleInfo>
<mods:nonSort>La</mods:nonSort>
<mods:title>difesa della razza</mods:title>
<mods:subTitle>scienza, documentazione, polemica</mods:subTitle>
<mods:partNumber>anno 1:n. 1</mods:partNumber>
</mods:titleInfo>
</mods:mods>
</wrap>
有没有什么办法可以强制实现我想要的效果?
谢谢
1 个回答
0
你可以先尝试插入 XInclude
元素,然后再用 .xinclude()
方法来处理它们(具体可以参考 文档)。这样做似乎能保留命名空间的声明(lxml 在解析器生成的情况下会保留这些声明,但如果你自己创建元素,或者把元素从一个文档移动到另一个文档时,它就不会保留了)。
需要注意的是,在你的情况下,你仍然需要更改元素的标签名:这些元素会按照原始文档中的样子被包含进来,没有任何命名空间,而你似乎在输出中把它们改成了带命名空间的元素名。
你可能需要使用一个 自定义解析器,这和文档中提到的 .xinclude()
不支持这个的说法相反(它确实使用了解析器来解析包含文档,但不支持将特定的解析器或解析器传递给 XInclude 处理)。
另外一个选择可能是基于 xslt 的解决方案。