pythonlxml&;从xpath开始?

pythonlxml&;从xpath开始?,python,xml,xpath,lxml,Python,Xml,Xpath,Lxml,对Python来说相当陌生,对XML来说非常陌生,更不用说试图解析它了。我需要从一系列weblogic XML配置文件中识别集群节点。我已经知道如何获得75%的利润;现在,我正在追查edge案件,我不确定如何继续 Weblogic XML配置文件从名称空间定义开始,然后是许多子元素,其中一些元素有自己的子元素 我感兴趣的元素是,它通常有一个名为的子元素,其中包含我要查找的主机名 按照“我们喜欢标准,我们有很多标准”的模式,这种模式并不适用于任何地方。在它不起作用的地方,我需要查找名为的的子元素。

对Python来说相当陌生,对XML来说非常陌生,更不用说试图解析它了。我需要从一系列weblogic XML配置文件中识别集群节点。我已经知道如何获得75%的利润;现在,我正在追查edge案件,我不确定如何继续

Weblogic XML配置文件从名称空间定义开始,然后是许多子元素,其中一些元素有自己的子元素

我感兴趣的元素是
,它通常有一个名为
的子元素,其中包含我要查找的主机名

按照“我们喜欢标准,我们有很多标准”的模式,这种模式并不适用于任何地方。在它不起作用的地方,我需要查找名为
的子元素。该元素包含一个别名,该别名在与
相同级别的不同根子级中展开

因此,这张图片价值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>
在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行代码……幸好我不是以写代码为生的:))


换言之,我需要在
子项下找到与相应
子项下的名称匹配的子项。从web上的一些示例中,我相信xpath可能会有所帮助,但我甚至无法让简单的示例正常工作。

下面是一个在文件中使用xpath的示例。我处理每个元素“domain”并显示“nameof*”,因为它们在同一级别

from lxml import etree
xp = etree.XPath('./*/name')
for event, elem in etree.iterparse("delme.xml", events=('end',), tag="domain"):
    for name in xp(elem):
        print(name.text)
输出:

EDIServices_MS1
EDIServices_MS2
EDIServices_MC1
EDIServices_MC2

编辑:创建一个粗糙的xpath来匹配这两种模式

添加一个可用的xml元素片段是每个xml文件一个还是有很多?提供一个有效的xml示例文档,特别是包括任何名称空间声明。这很重要;道歉:我试图避开经常被指责写作的文字墙。谢谢你看。
EDIServices_MS1
EDIServices_MS2
EDIServices_MC1
EDIServices_MC2