合理新来python和令人难以置信的新xml更少试图解析它。我需要从一系列weblogic xml配置文件中识别集群节点。我已经想出了如何获得75%现在,我正在追求边缘案例,我不确定如何继续。python lxml&开始w/xpath?
Weblogic xml配置文件以命名空间定义开头,然后是一些子元素,其中一些子元素有自己的子元素。
我感兴趣的元素是<server>
,它通常会包含一个名为<listen-address>
的子元素,其中包含我正在查找的主机名。
遵循“我们热爱标准,我们获得了很多标准”的范例,这种模式无处不在。如果它不起作用,我需要寻找名为<machine>
的<server>
的子元素。该元素包含在不同的根子项中展开的别名,与<server>
的级别相同。
所以,一张价值1000个字:
注:试图避免发送吨XML的;但显然,我在节省带宽方面的尝试使问题更难回答。道歉。我确实修剪了不需要的或与安全有关的子元素。
<?xml version='1.0' encoding='UTF-8'?>
<domain xmlns="http://xmlns.oracle.com/weblogic/domain" xmlns:sec="http://xmlns.oracle.com/weblogic/security" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:wls="http://xmlns.oracle.com/weblogic/security/wls" xsi:schemaLocation="http://xmlns.oracle.com/weblogic/security/wls http://xmlns.oracle.com/weblogic/security/wls/1.0/wls.xsd http://xmlns.oracle.com/weblogic/domain http://xmlns.oracle.com/weblogic/1.0/domain.xsd http://xmlns.oracle.com/weblogic/security/xacml http://xmlns.oracle.com/weblogic/security/xacml/1.0/xacml.xsd http://xmlns.oracle.com/weblogic/security/providers/passwordvalidator http://xmlns.oracle.com/weblogic/security/providers/passwordvalidator/1.0/passwordvalidator.xsd http://xmlns.oracle.com/weblogic/security http://xmlns.oracle.com/weblogic/1.0/security.xsd">
<name>EDIServices_Domain</name>
<domain-version>12.2.1.0.0</domain-version>
<security-configuration>
<name>EDIServices_Domain</name>
<default-realm>myrealm</default-realm>
<node-manager-username>snipped</node-manager-username>
<node-manager-password-encrypted>not_really_my_pwd</node-manager-password-encrypted>
</security-configuration>
<server>
<name>EDIServices_AS</name>
<listen-port>60010</listen-port>
<web-server>
<name>EDIServices_AS</name>
<web-server-log>
<file-name>/opt/app/oracle/user_projects/logs/EDIServices_Domain/access.log</file-name>
<file-count>24</file-count>
<file-min-size>10000</file-min-size>
<rotate-log-on-startup>true</rotate-log-on-startup>
<elf-fields>c-ip cs-uri date time cs-method cs-uri sc-status</elf-fields>
<log-file-format>common</log-file-format>
</web-server-log>
</web-server>
<listen-address></listen-address>
</server>
<server>
<name>EDIServices_MS1</name>
<machine>EDIServices_MC1</machine>
<listen-port>60014</listen-port>
<cluster>EDIServices_CS</cluster>
<listen-address></listen-address>
</server>
<server>
<name>EDIServices_MS2</name>
<machine>EDIServices_MC2</machine>
<listen-port>60014</listen-port>
<cluster>EDIServices_CS</cluster>
<listen-address></listen-address>
</server>
<cluster>
<name>EDIServices_CS</name>
<cluster-messaging-mode>unicast</cluster-messaging-mode>
<dynamic-servers>
<maximum-dynamic-server-count>0</maximum-dynamic-server-count>
</dynamic-servers>
</cluster>
<production-mode-enabled>true</production-mode-enabled>
<configuration-version>12.2.1.0.0</configuration-version>
<machine xsi:type="unix-machineType">
<name>EDIServices_MC1</name>
<node-manager>
<name>EDIServices_MC1</name>
<nm-type>SSL</nm-type>
<listen-address>host001</listen-address>
<listen-port>7001</listen-port>
</node-manager>
</machine>
<machine xsi:type="unix-machineType">
<name>EDIServices_MC2</name>
<node-manager>
<name>EDIServices_MC2</name>
<listen-address>host002</listen-address>
<listen-port>7001</listen-port>
</node-manager>
</machine>
</domain>
因此,在 '正常' 配置运行它,我得到:
$ ./lxml configs/EntsvcSoa_Domain_config.xml
EntsvcSoa_AS => host003.myco.com
EntsvcSoa_MS1 => host004.myco.com
EntsvcSoa_MS2 => host005.myco.com
运行它针对ABI正常的配置,我目前得到:
$ ./lxml configs/EDIServices_Domain_config.xml
EDIServices_MS1 => EDIServices_MC1
EDIServices_MS2 => EDIServices_MC2
使用上面的例子中,我想将EDIServices_MC1和EDIServices_MC2分别转换为host001和host002。
主回路是:
注:在被彻底的利益,这里是整个脚本:
#!/usr/bin/env python3
from lxml import etree
import re
import sys
import os
import pprint
if len(sys.argv) != 2:
print('Format: ./wl_clusters ${weblogic_config_file}')
sys.exit(1)
if not os.path.isfile(sys.argv[1]):
print('Format: ./wl_clusters ${weblogic_config_file}')
sys.exit(2)
config = sys.argv[1]
# set up lxml structures
tree = etree.parse(config)
root = tree.getroot()
# set up xml namespace govno
ns = root.nsmap[None]
namespaces = { 'ns': ns }
for server in root.findall('ns:server', namespaces):
cs = server.find('ns:cluster', namespaces)
if cs is None:
continue
# cluster_name = server.find('ns:cluster', namespaces).text
cluster_name = cs.text
listen_address = server.find('ns:listen-address', namespaces)
server_name = listen_address.text
if server_name is None:
machine = server.find('ns:machine', namespaces)
if machine is None:
continue
else:
server_name = machine.text
print("%-15s => %s" % (cluster_name, server_name))
(这是我花天编写代码12行...好东西我不这样做的生活:))
改编,我需要找到<machine>
孩子谁的名字匹配相应<server>
孩子下的名称。从网络上的一些例子来看,我相信xpath可能会有所帮助,但即使是简单的例子,我也无法得到。去图,我只是想出了一个命名空间是什么...
任何提示/技巧/建议非常赞赏,特别是完整的noob教程xpath。
谢谢你的时间。
Doug O'Leary
添加一个可用的xml片段 –
提供有效的XML示例文档,特别包括任何名称空间声明。这个很重要。 – Markus