2016-10-24 5 views
1

Relativ neu zu Python und unglaublich neu zu XML viel weniger versuchen, es zu analysieren. Ich muss Cluster-Knoten aus einer Reihe von XML-XML-Konfigurationsdateien identifizieren. Ich habe herausgefunden, wie man 75% von ihnen bekommt; jetzt gehe ich nach dem Randfall und ich bin unsicher, wie es weitergeht.Python LXml & starten mit Xpath?

Weblogic XML-Konfigurationsdateien beginnen mit Namespace-Definitionen dann eine Anzahl von Kind-Elemente, von denen einige eigene Kinder haben.

Das Element, das mich interessiert, ist <server>, die normalerweise ein Unterelement namens <listen-address> haben wird, das den Hostnamen enthält, nach dem ich suche.

Nach dem Paradigma von "wir lieben Standards, wir haben viele von ihnen", dieses Modell funktioniert nicht überall. Wo es nicht funktioniert, muss ich nach einem Subelement von <server> namens <machine> suchen. Dieses Element enthält einen Alias, der in einem anderen Stamm-Child auf derselben Ebene wie <server> erweitert wird.

So, Bild sagt mehr als 1000 Worte:

Hinweis: versuchte Tonnen xml zu vermeiden, zu senden; Aber anscheinend sind meine Versuche, die Bandbreite zu sparen, schwieriger zu beantworten. Entschuldigung. Ich habe nicht benötigte oder sicherheitsrelevante Kindelemente reduziert.

<?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> 

Also, es auf 'normalen' config ausgeführt wird, erhalte ich:

$ ./lxml configs/EntsvcSoa_Domain_config.xml 
EntsvcSoa_AS => host003.myco.com 
EntsvcSoa_MS1 => host004.myco.com 
EntsvcSoa_MS2 => host005.myco.com 

es gegen die abi-Normal-Config-Rennen, bin ich zur Zeit immer:

$ ./lxml configs/EDIServices_Domain_config.xml 
EDIServices_MS1 => EDIServices_MC1 
EDIServices_MS2 => EDIServices_MC2 

Verwendung In den obigen Beispielen möchte ich EDIServices_MC1 und EDIServices_MC2 zu host001 bzw. host002 übersetzen.

Der Primärkreislauf ist:

HINWEIS: im Interesse vollständig zu sein, hier ist das gesamte Skript:

#!/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)) 

(Es ist mir genommen Tage 12 Zeilen Code zu schreiben ... Gut, dass ich das nicht für einen Lebensunterhalt mache :))

Umformuliert, muss ich die unter dem <machine> Kind finden, dessen Name mit dem Namen unter dem entsprechenden <server> Kind übereinstimmt. Von einigen Beispielen im Web glaube ich, dass xpath helfen könnte, aber ich konnte nicht einmal die einfachen Beispiele zum Laufen bringen. Go Figur, ich habe gerade herausgefunden, was ein Namespace ist ...

Alle Hinweise/Tipps/Vorschläge sehr geschätzt vor allem mit vollständigen Noob Tutorials für Xpath.

Danke für Ihre Zeit.

Doug O'Leary

+1

Fügen Sie ein brauchbares Snippet des xml –

+0

Element ist eine pro XML-Datei oder es gibt viele von ihnen? – Muposat

+0

Stellen Sie ein gültiges XML-Beispieldokument bereit, das insbesondere alle Namespacedeklarationen enthält. Das ist wichtig. – Markus

Antwort

-1

Hier ist ein Beispiel von XPath mit Ihrer Datei. Ich verarbeite jedes Element "domain" und zeige "names of *", was funktioniert, da sie sich auf derselben Ebene befinden.

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) 

Ausgang:

EDIServices_MS1 
EDIServices_MS2 
EDIServices_MC1 
EDIServices_MC2 

Edit: erstellt ein rohes XPath beide Muster übereinstimmen.