在 python 中解析 xml 并更改名称空间属性

问题描述 投票:0回答:1

我正在向 URL 发出请求,在我得到的 xml 响应中,xmlns 属性命名空间会不时发生变化。因此,当我对命名空间进行硬编码时,找到一个元素将返回 None 。请帮忙。

例如我得到以下 xml。

<package xmlns="http://schemas.microsoft.com/packaging/2012/06/nuspec.xsd">
<metadata>
<id>SharpZipLib</id>
<version>1.1.0</version>
<authors>ICSharpCode</authors>
<owners>ICSharpCode</owners>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<licenseUrl>https://github.com/icsharpcode/SharpZipLib/blob/master/LICENSE.txt</licenseUrl>
<projectUrl>https://github.com/icsharpcode/SharpZipLib</projectUrl>
<description>SharpZipLib (#ziplib, formerly NZipLib) is a compression library for Zip, GZip, BZip2, and Tar written entirely in C# for .NET. It is implemented as an assembly (installable in the GAC), and thus can easily be incorporated into other projects (in any .NET language)</description>
<releaseNotes>Please see https://github.com/icsharpcode/SharpZipLib/wiki/Release-1.1 for more information.</releaseNotes>
<copyright>Copyright © 2000-2018 SharpZipLib Contributors</copyright>
<tags>Compression Library Zip GZip BZip2 LZW Tar</tags>
<repository type="git" url="https://github.com/icsharpcode/SharpZipLib" commit="45347c34a0752f188ae742e9e295a22de6b2c2ed"/>
<dependencies>
<group targetFramework=".NETFramework4.5"/>
<group targetFramework=".NETStandard2.0"/>
</dependencies>
</metadata>
</package>

现在查看 xmlns 属性。整个属性是相同的,但有时“2012/06”部分对于某些响应会不时发生变化。我有以下 python 脚本。请参阅

ns = {'nuspec': 'http://schemas.microsoft.com/packaging/2013/05/nuspec.xsd'}
行。我无法像这样对命名空间进行硬编码。是否有任何替代方案,例如使用正则表达式等来映射名称空间。仅日期部分发生变化,即某些回复中的 2013/05 为 2012/04 等。

def fetch_nuget_spec(self, versioned_package):
        name = versioned_package.package.name.lower()
        version = versioned_package.version.lower()
        url = f'https://api.nuget.org/v3-flatcontainer/{name}/{version}/{name}.nuspec'
        response = requests.get(url)
        metadata = ET.fromstring(response.content)
        ns = {'nuspec': 'http://schemas.microsoft.com/packaging/2013/05/nuspec.xsd'}
        license = metadata.find('./nuspec:metadata/nuspec:license', ns)
        if license is None:
            license_url=metadata.find('./nuspec:metadata/nuspec:licenseUrl', ns)
            if license_url is None:
                return { 'license': 'Not Found'  }
            return {'license':license_url.text}
        else:
            if len(license.text)==0:
                print('SHIT')
            return { 'license': license.text  }

  
python xml elementtree
1个回答
0
投票

如果使用

lxml
是一个选项,那么它可以帮助列出像

这样的命名空间
from lxml import etree
doc = etree.parse("tmp.xml")
nslst = doc.xpath('/*/namespace::*')
print(nslst[1][1])
# http://schemas.microsoft.com/packaging/2012/06/nuspec.xsd
ns = {'nuspec': nslst[1][1]}
print(ns)
# {'nuspec': 'http://schemas.microsoft.com/packaging/2012/06/nuspec.xsd'}

同时使用

lxml
xml.etree.ElementTree
可能意味着文档将被解析两次,因此如果可能的话只应使用 lxml,因为它具有更完整的 XML 和 XPath 实现。
如果不可能,可以使用 lxml 解析结果中的 ET

>>> tree = ET.ElementTree(doc)
>>> tree.find('./nuspec:metadata/nuspec:licenseUrl', ns)
<Element {http://schemas.microsoft.com/packaging/2012/06/nuspec.xsd}licenseUrl at 0x7fe019ea1cc8>
© www.soinside.com 2019 - 2024. All rights reserved.