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

时间:2010-08-25 19:54:08

标签: python serialization namespaces lxml xml-namespaces

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

例如,我有文件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 :(得分:0)

您可以先尝试插入XInclude元素,然后使用.xinclude()方法解析它们(请参阅docs)。这似乎保留了名称空间声明(lxml在它们来自解析器时保留它们,但是当你自己创建元素时,或者将元素从一个文档移动到另一个文档时不会保留它们)

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

您可能必须使用custom resolver,这与文档似乎对.xinclude()不支持此内容的说法相反(它确实使用了用于解析包含文档的解析器中的解析器,它只是不支持将特定的解析器或解析器传递给XInclude处理。)

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