使用 python 解析 pom.xml 文件在旧的 python 版本中不起作用
Parsing pom.xml file with pythin doesn't work in older python versions
让我从一个明显的事实开始,我不是 python 开发人员 - 我主要用其他语言编写代码,因此如果这个问题有一个“明显”的答案,请原谅。
我写了一个非常简单的 PomParser
class 它应该用作 ElementTree
的包装器并且 return 来自 pom.xml
文件作为字符串。下面的代码在 Python 3.8 中工作正常,但在 Python >= 3 && < 3.8.
中不起作用
import xml.etree.ElementTree as ET
import sys
from pathlib import Path
class PomParser:
data = """<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<groupId>org.example</groupId>
<scm><connection>scm:git:git://github.com</connection></scm>
</project>
"""
tree = None
namespaces = {'': 'http://maven.apache.org/POM/4.0.0'}
def __init__(self):
self.tree = ET.fromstring(self.data)
def getTree(self):
return self.tree
def getGroupId(self):
return self.findTextByXpath("./groupId")
def findTextByXpath(self, xpath: str):
element = self.findByXpath(xpath)
return element.text if element is not None else None
def findByXpath(self, xpath: str):
return self.tree.find(xpath, self.namespaces)
parser = PomParser()
print("Python: ", sys.version)
print("Without defining namespace: ", parser.findTextByXpath("./groupId"))
print("Explicitly defining namespace: ", parser.getTree().findtext("./{http://maven.apache.org/POM/4.0.0}groupId"))
如果您通过 rept.it 运行 这段代码(example,它使用 Python 3.8,它将打印:
Python: 3.8.3 (default, May 14 2020, 20:11:43)
[GCC 7.5.0]
Without defining namespace: org.example
Explicitly defining namespace: org.example
但是,如果您 运行 https://www.onlinegdb.com/online_python_compiler 中的相同代码,它似乎使用 Python 3.4 - 它将打印:
Python: 3.4.3 (default, Nov 12 2018, 22:25:49)
[GCC 4.8.4]
Without defining namespace: None
Explicitly defining namespace: org.example
我使用 onlinegdb 只是因为它重现了我在 Netlify 中使用相同代码时遇到的问题,最新版本是 Python 3.7(实际上是我要添加支持的目标版本)
我想知道我在这里错过了什么?
我真的 需要在 xpath 过滤器中显式定义命名空间吗?
如果是这样的话——那么在什么都不做的情况下能够将 namespaces
定义为参数的目的是什么?
这与 Python 3.8 中的更改有关。在该版本中,可以将空字符串作为名称空间映射中的前缀。这在早期版本中不起作用。
如果你改变
namespaces = {'': 'http://maven.apache.org/POM/4.0.0'}
至
namespaces = {'p': 'http://maven.apache.org/POM/4.0.0'}
并改变
./groupId
至
./p:groupId
它应该适用于所有版本的 Python 3.
让我从一个明显的事实开始,我不是 python 开发人员 - 我主要用其他语言编写代码,因此如果这个问题有一个“明显”的答案,请原谅。
我写了一个非常简单的 PomParser
class 它应该用作 ElementTree
的包装器并且 return 来自 pom.xml
文件作为字符串。下面的代码在 Python 3.8 中工作正常,但在 Python >= 3 && < 3.8.
import xml.etree.ElementTree as ET
import sys
from pathlib import Path
class PomParser:
data = """<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<groupId>org.example</groupId>
<scm><connection>scm:git:git://github.com</connection></scm>
</project>
"""
tree = None
namespaces = {'': 'http://maven.apache.org/POM/4.0.0'}
def __init__(self):
self.tree = ET.fromstring(self.data)
def getTree(self):
return self.tree
def getGroupId(self):
return self.findTextByXpath("./groupId")
def findTextByXpath(self, xpath: str):
element = self.findByXpath(xpath)
return element.text if element is not None else None
def findByXpath(self, xpath: str):
return self.tree.find(xpath, self.namespaces)
parser = PomParser()
print("Python: ", sys.version)
print("Without defining namespace: ", parser.findTextByXpath("./groupId"))
print("Explicitly defining namespace: ", parser.getTree().findtext("./{http://maven.apache.org/POM/4.0.0}groupId"))
如果您通过 rept.it 运行 这段代码(example,它使用 Python 3.8,它将打印:
Python: 3.8.3 (default, May 14 2020, 20:11:43)
[GCC 7.5.0]
Without defining namespace: org.example
Explicitly defining namespace: org.example
但是,如果您 运行 https://www.onlinegdb.com/online_python_compiler 中的相同代码,它似乎使用 Python 3.4 - 它将打印:
Python: 3.4.3 (default, Nov 12 2018, 22:25:49)
[GCC 4.8.4]
Without defining namespace: None
Explicitly defining namespace: org.example
我使用 onlinegdb 只是因为它重现了我在 Netlify 中使用相同代码时遇到的问题,最新版本是 Python 3.7(实际上是我要添加支持的目标版本)
我想知道我在这里错过了什么?
我真的 需要在 xpath 过滤器中显式定义命名空间吗?
如果是这样的话——那么在什么都不做的情况下能够将 namespaces
定义为参数的目的是什么?
这与 Python 3.8 中的更改有关。在该版本中,可以将空字符串作为名称空间映射中的前缀。这在早期版本中不起作用。
如果你改变
namespaces = {'': 'http://maven.apache.org/POM/4.0.0'}
至
namespaces = {'p': 'http://maven.apache.org/POM/4.0.0'}
并改变
./groupId
至
./p:groupId
它应该适用于所有版本的 Python 3.