You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python解析xmlns属性动态变化的XML问题

解决动态命名空间下XML元素查找问题

问题背景

请求NuGet的nupsec XML时,根元素xmlns属性中的日期段(如2012/06、2013/05)会动态变化,硬编码命名空间后,xml.etree.ElementTree无法定位元素,返回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>

原问题代码:

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  }

方案1:动态提取命名空间(推荐)

直接从XML根元素提取xmlns属性值,无需关心日期段变化,是最可靠的XML处理方式。

修改后的代码:

import xml.etree.ElementTree as ET
import requests

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)
    root = ET.fromstring(response.content)
    
    # 动态获取根元素的命名空间
    ns = {'nuspec': root.attrib.get('xmlns', '')}
    
    # 优先查找<license>
    license_elem = root.find('./nuspec:metadata/nuspec:license', ns)
    if license_elem is not None:
        license_text = license_elem.text.strip() if license_elem.text else 'Not Found'
        return {'license': license_text}
    
    # 找不到则查找<licenseUrl>
    license_url_elem = root.find('./nuspec:metadata/nuspec:licenseUrl', ns)
    if license_url_elem is not None:
        return {'license': license_url_elem.text.strip()}
    
    return {'license': 'Not Found'}

方案2:正则表达式匹配(不推荐)

仅当XML结构简单且稳定时使用,正则处理XML容易因标签嵌套、属性变化等出现错误。

示例代码:

import re
import requests

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)
    xml_content = response.text
    
    # 匹配<license>标签内容
    license_match = re.search(r'<license[^>]*>(.*?)</license>', xml_content, re.DOTALL)
    if license_match:
        license_text = license_match.group(1).strip()
        return {'license': license_text if license_text else 'Not Found'}
    
    # 匹配<licenseUrl>标签内容
    license_url_match = re.search(r'<licenseUrl[^>]*>(.*?)</licenseUrl>', xml_content, re.DOTALL)
    if license_url_match:
        return {'license': license_url_match.group(1).strip()}
    
    return {'license': 'Not Found'}

内容的提问来源于stack exchange,提问作者nikhil

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 04:34:54