Wel*_*lsh 9 python xml xml-parsing python-2.7
我有一个pom文件,具有以下定义:
<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">
<modelVersion>4.0.0</modelVersion>
<groupId>org.welsh</groupId>
<artifactId>my-site</artifactId>
<version>1.0.0</version>
<packaging>pom</packaging>
<profiles>
<profile>
<build>
<plugins>
<plugin>
<groupId>org.welsh.utils</groupId>
<artifactId>site-tool</artifactId>
<version>1.0</version>
<executions>
<execution>
<configuration>
<mappings>
<property>
<name>homepage</name>
<value>/content/homepage</value>
</property>
<property>
<name>assets</name>
<value>/content/assets</value>
</property>
</mappings>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>
Run Code Online (Sandbox Code Playgroud)
我期待建立一个字典断name和value下元素property下mappings元素.
那么,我想弄清楚如何得到所有可能的mappings元素(柜面的多个生成配置文件),所以我可以得到所有property在它之下,并从阅读内容支持的XPath语法以下应打印出所有可能的文本/值元素:
import xml.etree.ElementTree as xml
pomFile = xml.parse('pom.xml')
root = pomFile.getroot()
for mapping in root.findall('*/mappings'):
for prop in mapping.findall('.//property'):
logging.info(prop.find('name').text + " => " + prop.find('value').text)
Run Code Online (Sandbox Code Playgroud)
什么都没有回来.我尝试打印出所有mappings元素并得到:
>>> print root.findall('*/mappings')
[]
Run Code Online (Sandbox Code Playgroud)
当我打印出root我得到的所有内容时:
>>> print root.findall('*')
[<Element '{http://maven.apache.org/POM/4.0.0}modelVersion' at 0x10b38bd50>, <Element '{http://maven.apache.org/POM/4.0.0}groupId' at 0x10b38bd90>, <Element '{http://maven.apache.org/POM/4.0.0}artifactId' at 0x10b38bf10>, <Element '{http://maven.apache.org/POM/4.0.0}version' at 0x10b3900d0>, <Element '{http://maven.apache.org/POM/4.0.0}packaging' at 0x10b390110>, <Element '{http://maven.apache.org/POM/4.0.0}name' at 0x10b390150>, <Element '{http://maven.apache.org/POM/4.0.0}properties' at 0x10b390190>, <Element '{http://maven.apache.org/POM/4.0.0}build' at 0x10b390310>, <Element '{http://maven.apache.org/POM/4.0.0}profiles' at 0x10b390390>]
Run Code Online (Sandbox Code Playgroud)
这让我试着打印:
>>> print root.findall('*/{http://maven.apache.org/POM/4.0.0}mappings')
[]
Run Code Online (Sandbox Code Playgroud)
但那也没有用.
任何建议都会很棒.
谢谢,
问题中代码的主要问题是
*/而不是//which 只匹配直接子级。正如您在 XML 文件的顶部所看到的,Maven使用名称空间http://maven.apache.org/POM/4.0.0。xmlns根节点中的属性定义了默认命名空间。该属性xmlns:xsi定义了一个仅用于 的命名空间xsi:schemaLocation。
<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">
Run Code Online (Sandbox Code Playgroud)
要像profile在方法中一样指定标签find,您还必须指定命名空间。例如,您可以编写以下内容来查找所有profile-tags。
import xml.etree as xml
pom = xml.parse('pom.xml')
for profile in pom.findall('//{http://maven.apache.org/POM/4.0.0}profile'):
print(repr(profile))
Run Code Online (Sandbox Code Playgroud)
另请注意,我正在使用//. */对于上面的特定 xml 文件,使用将产生相同的结果。但是,它不适用于其他标签,例如mappings. 由于*仅表示一级,*/child因此可以扩展为parent/tag或xyz/tag但不能扩展为xyz/parent/tag。
现在,您应该能够想出这样的方法来查找所有映射:
pom = xml.parse('pom.xml')
map = {}
for mapping in pom.findall('//{http://maven.apache.org/POM/4.0.0}mappings'
'/{http://maven.apache.org/POM/4.0.0}property'):
name = mapping.find('{http://maven.apache.org/POM/4.0.0}name').text
value = mapping.find('{http://maven.apache.org/POM/4.0.0}value').text
map[name] = value
Run Code Online (Sandbox Code Playgroud)
像这样指定命名空间非常冗长。为了更容易阅读,您可以定义一个命名空间映射并将其作为第二个参数传递给findand findall:
# ...
nsmap = {'m': 'http://maven.apache.org/POM/4.0.0'}
for mapping in pom.findall('//m:mappings/m:property', nsmap):
name = mapping.find('m:name', nsmap).text
value = mapping.find('m:value', nsmap).text
map[name] = value
Run Code Online (Sandbox Code Playgroud)
好的,发现当我从project元素中删除 Maven 内容时,我只能<project>这样做:
for mapping in root.findall('*//mappings'):
logging.info(mapping)
for prop in mapping.findall('./property'):
logging.info(prop.find('name').text + " => " + prop.find('value').text)
Run Code Online (Sandbox Code Playgroud)
这会导致:
INFO:root:<Element 'mappings' at 0x10d72d350>
INFO:root:homepage => /content/homepage
INFO:root:assets => /content/assets
Run Code Online (Sandbox Code Playgroud)
然而,如果我把 Maven 的东西留在顶部,我可以这样做:
for mapping in root.findall('*//{http://maven.apache.org/POM/4.0.0}mappings'):
logging.info(mapping)
for prop in mapping.findall('./{http://maven.apache.org/POM/4.0.0}property'):
logging.info(prop.find('{http://maven.apache.org/POM/4.0.0}name').text + " => " + prop.find('{http://maven.apache.org/POM/4.0.0}value').text)
Run Code Online (Sandbox Code Playgroud)
结果是:
INFO:root:<Element '{http://maven.apache.org/POM/4.0.0}mappings' at 0x10aa7f310>
INFO:root:homepage => /content/homepage
INFO:root:assets => /content/assets
Run Code Online (Sandbox Code Playgroud)
然而,我很想知道如何避免考虑 Maven 的东西,因为它把我限制在这种格式中。
编辑:
好吧,我设法得到了一些更详细的内容:
import xml.etree.ElementTree as xml
def getMappingsNode(node, nodeName):
if node.findall('*'):
for n in node.findall('*'):
if nodeName in n.tag:
return n
else:
return getMappingsNode(n, nodeName)
def getMappings(rootNode):
mappingsNode = getMappingsNode(rootNode, 'mappings')
mapping = {}
for prop in mappingsNode.findall('*'):
key = ''
val = ''
for child in prop.findall('*'):
if 'name' in child.tag:
key = child.text
if 'value' in child.tag:
val = child.text
if val and key:
mapping[key] = val
return mapping
pomFile = xml.parse('pom.xml')
root = pomFile.getroot()
mappings = getMappings(root)
print mappings
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
7861 次 |
| 最近记录: |