Skip to main content
 首页 » 编程设计

python之使用 lxml 保留子元素命名空间序列化

2025年05月04日11java哥

我有几个不同的 XML 文档,我正试图使用​​ lxml 将它们合并为一个文档。问题是我需要结果来保留每个子文档根节点上的命名空间。 Lxml 似乎想将任何多次使用的 namespace 声明推送到新文档的根目录,这会破坏我的应用程序(这是一个公认的错误)。

例如,我有文档 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> 

有什么想法可以强制执行我想要的行为吗?

谢谢

请您参考如下方法:

您可以先尝试插入 XInclude 元素,然后使用 .xinclude() 方法解析它们(参见 docs )。这似乎保留了 namespace 声明(lxml 在它们源自解析器时保留它们,但在您自己创建元素或将元素从一个文档移动到另一个文档时不保留)

请注意,在您的情况下,您仍然需要更改元素的标签名称:它们将按原样包含在原始文档中,没有任何命名空间,而您似乎已将它们更改为命名空间元素名称你的输出。

您可能必须使用 custom resolver ,与文档似乎所说的关于 .xinclude() 不支持这一点相反(它确实使用解析器中的解析器来解析包含的文档,它只是不支持传递特定的解析器或 XInclude 处理的解析器)。

另一个选择可能是基于 xslt 的解决方案。