Search code examples
pythonxmlxpathlxml

How do I get python lxml to find this element?


Given a XML file of this structure:

<log>
    <Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">
        <System>
            <EventID>1</EventID> # if this is 1
        </System>
        <EventData>
            <Data Name="CommandLine">C:\Windows\system32\wbem\unsecapp.exe -Embedding</Data> # then I want this value
        </EventData>
    </Event>
  <Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">
        <System>
            <EventID>2</EventID>
        </System>
        <EventData>
            <Data Name="CommandLine">C:\Windows\system32\wbem\unsecapp.exe -Embedding</Data>
        </EventData>
    </Event>
</log>

I want to check all <Event> if the <EventID> = 1 and then use the value of <Data Name='CommandLine'>

Using this code

from lxml import etree as ET

with open(log_file_path, 'r', encoding='utf-8') as file:                                                                     
    log_content = file.read()   
root = ET.fromstring(log_content)

ns = {'ns' : 'http://schemas.microsoft.com/win/2004/08/events/event'}

root.xpath("//ns:Event[System/EventID='1']/EventData/Data[@Name='CommandLine']", namespaces=ns)

finds nothing.

I tried the same xpath query //Event[System/EventID='1']/EventData/Data[@Name='CommandLine'] in an online xpath tool with the same xml and it works as intended.

I can't figure out the problem, any ideas?


Solution

  • A default namespace on an element applies to its descendant elements too, so change

    //ns:Event[System/EventID='1']/EventData/Data[@Name='CommandLine']

    to

    //ns:Event[ns:System/ns:EventID='1']/ns:EventData/ns:Data[@Name='CommandLine']