XML Parsing with Python's lxml Library: XPath Queries for Elements, Attributes, and Text Content

Introduction to XML Parsing with lxml

The lxml library in Python provides powerful tools for parsing XML documents and performing XPath queries. This tutorial demonstrates how to navigate XML structures, access elements, attributes, and text content using XPath expressions.

Sample XML Document

Consider the following XML structure which we'll use for our examples:

<?xml version="1.0" encoding="UTF-8"?>
<country name="chain">
    <provinces>
        <heilongjiang name="citys">
            <haerbin/>
            <daqing/>
        </heilongjiang>
        <guangdong name="citys">
            <guangzhou/>
            <shenzhen/>
            <huhai/>
        </guangdong>
        <taiwan name="citys">
            <taibei/>
            <gaoxiong/>
        </taiwan>
        <xinjiang name="citys">
            <wulumuqi waith="tianqi">晴</wulumuqi>
        </xinjiang>
    </provinces>
</country>

Basic XML Parsing with lxml

Here's how to parse an XML file and extract basic information:

from lxml import etree

class XMLProcessor:
    def __init__(self, file_path):
        self.parser = etree.parse(file_path)
        self.root = self.parser.getroot()
    
    def display_xml_structure(self):
        # Print the entire XML document
        print(etree.tostring(self.parser))
        
        # Get root element information
        print(f"Root tag: {self.root.tag}")
        print(f"Root attributes: {self.root.items()}")
        
        # Iterate through direct children of root
        for child in self.root:
            print(f"Child tag: {child.tag}")
            print(f"Child attributes: {child.items()}")
            print(f"Child text: {child.text}")
            
            # Iterate through grandchildren
            for grandchild in child:
                print(f"Grandchild tag: {grandchild.tag}")
                print(f"Grandchild attributes: {grandchild.items()}")
                print(f"Grandchild text: {grandchild.text}")
                
                # Iterate through great-grandchildren if they exist
                for great_grandchild in grandchild:
                    print(f"Great-grandchild tag: {great_grandchild.tag}")
                    print(f"Great-grandchild attributes: {great_grandchild.items()}")
                    print(f"Great-grandchild text: {great_grandchild.text}")

# Usage
if __name__ == '__main__':
    processor = XMLProcessor('data.xml')
    processor.display_xml_structure()

XPath Queries for Specific Elements

XPath allows you to select nodes in an XML document. Here are some example:

class XPathExtractor:
    def __init__(self, file_path):
        self.parser = etree.parse(file_path)
    
    def extract_all_nodes(self):
        # Extract all nodes in the document
        all_nodes = self.parser.xpath('//node()')
        print(f"Total nodes found: {len(all_nodes)}")
        return all_nodes
    
    def extract_elements_by_tag(self, tag_name):
        # Extract all elements with a specific tag
        elements = self.parser.xpath(f'//{tag_name}')
        return elements
    
    def extract_elements_with_attributes(self, tag_name, attribute_name, attribute_value):
        # Extract elements with specific attribute values
        elements = self.parser.xpath(f'//{tag_name}[@{attribute_name}="{attribute_value}"]')
        return elements
    
    def extract_child_elements(self, parent_tag):
        # Extract all direct child elements of a specific parent
        children = self.parser.xpath(f'//{parent_tag}/*')
        return children

# Usage
if __name__ == '__main__':
    extractor = XPathExtractor('data.xml')
    
    # Get all nodes
    all_nodes = extractor.extract_all_nodes()
    
    # Get all elements with tag 'heilongjiang'
    heilongjiang_elements = extractor.extract_elements_by_tag('heilongjiang')
    
    # Get all child elements of 'heilongjiang'
    heilongjiang_children = extractor.extract_child_elements('heilongjiang')
    
    # Process and display results
    for element in heilongjiang_children:
        print(f"Element: {element.tag}, Attributes: {element.items()}, Text: {element.text}")

Handling XML Namespaces

When working with XML documents that use namespaces, you need to handle them properly:

<?xml version="1.0" encoding="UTF-8"?>
<country name="chain">
    <provinces>
        <city:table xmlns:city="http://www.w3school.com.cn/furniture">
            <heilongjiang name="citys">
                <city:haerbin/>
                <city:daqing/>
            </heilongjiang>
            <guangdong name="citys">
                <city:guangzhou/>
                <city:shenzhen/>
                <city:zhuhai/>
            </guangdong>
        </city:table>    
    </provinces>
</country>

Processing Namespaced XML

class NamespacedXMLProcessor:
    def __init__(self, file_path):
        self.parser = etree.parse(file_path)
        # Register the namespace to use a prefix
        namespaces = {'ns': 'http://www.w3school.com.cn/furniture'}
        self.namespaces = namespaces
    
    def extract_all_elements_without_whitespace(self):
        # Get all nodes and filter out whitespace
        all_nodes = self.parser.xpath('//node()')
        elements_only = []
        
        for node in all_nodes:
            if isinstance(node, str) and (node.strip() == '' or node.strip() == '\n'):
                continue
            elements_only.append(node)
        
        return elements_only
    
    def extract_namespaced_elements(self):
        # Extract elements with namespace
        elements = self.parser.xpath('//ns:table', namespaces=self.namespaces)
        return elements
    
    def extract_all_child_elements(self, parent_tag):
        # Extract all child elements regardless of namespace
        children = self.parser.xpath(f'//{parent_tag}/*')
        return children

# Usage
if __name__ == '__main__':
    ns_processor = NamespacedXMLProcessor('namespaced_data.xml')
    
    # Get all elements, filtering out whitespace
    all_elements = ns_processor.extract_all_elements_without_whitespace()
    for element in all_elements:
        if hasattr(element, 'tag'):
            print(f"Element: {element.tag}")
    
    # Get namespaced elements
    table_elements = ns_processor.extract_namespaced_elements()
    for element in table_elements:
        print(f"Namespaced element: {element.tag}")
    
    # Get all child elements of 'heilongjiang'
    heilongjiang_children = ns_processor.extract_all_child_elements('heilongjiang')
    for child in heilongjiang_children:
        print(f"Child element: {child.tag}, Attributes: {child.items()}, Text: {child.text}")

Key Methods and Properties

When working with lxml elements, these properties and methods are essential:

  • element.tag - Returns the tag name of the element
  • element.items() - Returns a list of (attribute_name, attribute_value) tuples
  • element.text - Returns the text content of the element
  • element.xpath('expression') - Performs a XPath query starting from this element
  • element.get('attribute_name') - Returns the value of a specific attribute

Understanding thece methods allows you to effectively navigate and extract information from XML documents using XPath expressions.

Tags: lxml XML xpath python parsing

Posted on Fri, 10 Jul 2026 16:16:25 +0000 by derrick24