Concepts / Extracting Attributes and Text from XML Elements

Extracting Attributes and Text from XML Elements

findall retrieves a Python list of all XML nodes matching a specified path, enabling batch processing of similar structures.

  • Programming
Interactive lab

Try it: XML Element Trees

How ET.fromstring() turns XML text into a tree of Elements (tag, attributes, .text), and how find(), findall() and iter() walk that tree along a path such as users/user.

How it works

  1. The parser reads start tags, text and end tags left to right, keeping a stack of open elements; each start tag becomes an Element that is a child of the element on top of the stack.
  2. Text before an element's first child becomes its .text (whitespace included); an end tag must match the open element or parsing stops with ParseError.
  3. findall(path) starts at the element it is called on (the root is not part of the path) and follows each path segment down one level of children.
  4. find(path) returns the first match or None; iter(tag) visits every element in document order, including the root.
  5. Reading .text, .tag or .get('attr') on each result gives the extracted values; reading an attribute from None raises AttributeError.

Default run (29 steps): ET.fromstring() receives 183 characters. The parser reads tags left to right and keeps a stack of open elements. … findall() returned a list of 2 elements; reading e.get('x') from each gives ['2', '7'].

Simplified: A small, hand-written XML parser for a subset: elements, attributes, text, self-closing tags, comments, CDATA, processing instructions and the five predefined entities plus numeric character references. DOCTYPE/DTDs and namespaces are not supported. Error messages follow Python's expat parser for these cases (column numbers can differ for non-ASCII documents). Paths support tags, *, ., //, [@attr], [@attr='v'], [tag] and [n].

Educational simulation

Loading the simulation…

From Repeated XML to Python Data

When XML contains several similar structures, such as multiple user elements, extracting only one node is not enough. The useful pattern is to find every matching node, receive those nodes as a Python list, and process the list with a for loop. This avoids writing separate extraction code for each user or record.

python
userpathuserChucklsttwo Element objectsuserBrentmatchesmatchesincluded inincluded in
What does findall return, and how does one XML path become a Python list containing multiple matching XML nodes?

Selecting Matching Elements

findall retrieves a Python list containing all XML nodes that match the path supplied to it. In the example, root.findall("user") searches the parsed XML tree below the users container for user elements. The path determines which elements are selected from the document hierarchy.

Worked example

Checking the Matching User Nodes

Determine what lst contains after root.findall("user") runs on the two-user XML document.

  1. 1
    Search

    The path user is applied to the parsed XML tree below root.

  2. 2
    Match

    Both user elements match the supplied path.

  3. 3
    Collect

    findall places the two matching XML nodes into the Python list named lst.

  4. 4
    Confirm

    The list length is two, so the query located both users before the loop begins.

Result

lst is a Python list containing two Element objects, one for Chuck and one for Brent.

Output
2
usersuserChuckid001userBrentnameChuckcontainscontainscontainscontains
How does the path supplied to findall determine which XML elements are selected from the document hierarchy?

Walking Through the List

After findall returns, a for loop visits each Element in the list one at a time. The loop variable represents the current XML node. During the first iteration, item represents the first user. During the second iteration, item represents the second user. The loop body runs once for each item and stops after all list items have been processed.

Code walkthrough
for item in lst:
    print(item.find("name").text)
    print(item.get("x"))
  1. 1
    The for statement takes the next Element from lst and binds it to item.
  2. 2
    The first pass uses the user element for Chuck.
  3. 3
    The loop body extracts and prints data from that current element.
  4. 4
    The second pass binds item to the user element for Brent.
  5. 5
    The same loop body runs again with Brent's data.
  6. 6
    The loop stops after both elements have been processed.
Output
Chuck
2
Brent
7
lsttwo Element objectsitemChuckloop completeitemBrentfirst itemnext itemno items remain
How does a for loop move from one XML node in the findall result to the next, and what does the loop variable represent at each step?

Reading Child Text and Attributes

XML data inside a matched node can appear as child-element text or as an attribute on the element itself. Use item.find("name").text to locate the name child element and read the text between its tags. Use item.get("x") to retrieve the x attribute directly from the current user element. Attributes belong to the element being processed, so find is not needed before get.

ExpressionWhat it accessesValue for Chuck
item.find("name")The name child elementThe name Element
item.find("name").textText inside the name child elementChuck
item.get("x")The x attribute on the user element2

The child element and attribute are accessed through different methods.

usercurrent Elementnamechild ElementChuckfindtext
How does a loop move from a matched parent node to a child element and then to that child element's text value?
userx2nameChuckgetfind
Where are attribute values stored on an XML node, and how does get retrieve a named attribute while processing each matching node?

Tracing One Complete Pass

Worked example

Processing Both Users

Explain what the loop extracts from each user element.

  1. 1
    First iteration

    item is bound to the first user Element. item.find("name").text gives Chuck, and item.get("x") gives 2.

  2. 2
    Second iteration

    item is rebound to the second user Element. item.find("name").text gives Brent, and item.get("x") gives 7.

  3. 3
    Completion

    The loop has visited both Elements in the list, so it stops.

Result

The extraction produces the name and x attribute for each user: Chuck with 2, followed by Brent with 7.

What do you think happens?

What will the loop print when it processes the two user elements in order?

  • Chuck, 2, Brent, 7

  • The list object only

  • Brent, 7, Chuck, 2

Reveal answer
Answer:

Chuck, 2, Brent, 7

The loop visits the first user before the second user, and the same extraction statements run on each current Element.

Diagnosing Empty or Failing Loops

When iteration does not produce the expected result, inspect findall before changing the loop. First check the list length and inspect the first item. If len(lst) is 0, the path may be wrong or the XML structure may not match the expected structure. If the list length is correct but extraction fails inside the loop, inspect each item and verify the child-element and attribute names exactly. XML names are case-sensitive.

  • Common mistake

    Treating the result of findall as one XML node instead of a list.

    What it looks like

    Using the list returned by findall as though it were the current user Element.

    Why it fails

    findall returns a Python list containing matching Element objects. The individual Element is available inside the for loop through its loop variable.

    Do this instead

    Loop over the list and call find or get on the current item.

  • Common mistake

    Assuming an empty list means the loop is broken.

    What it looks like

    The loop runs zero times because len(lst) is 0.

    Why it fails

    A zero-length list means no elements matched the supplied path, so there is no item for the loop to process.

    Do this instead

    Check the path and compare it with the XML hierarchy.

  • Common mistake

    Using the wrong child-element or attribute name.

    What it looks like

    Requesting a name that does not exactly match the XML name.

    Why it fails

    XML is case-sensitive, so names must match exactly.

    Do this instead

    Inspect the current item and verify the child and attribute names before extracting.

lstlist of Element objectsfinditemone Elementgetfor loop selects onechild elementattribute
What is the difference between the list returned by findall and a single XML node, and why can using the wrong one cause iteration or extraction failures?
Best practice

Debug in two stages: first confirm that findall selected the expected number of nodes, then inspect the current item inside the loop before attempting to extract child text or attributes.

Practice the Extraction Pattern

MEDIUM

Given the two-user XML structure from this article, write a loop that processes every element in lst and retrieves each user's id text, name text, and x attribute. Before the loop, include a check of the list length.

Hints
  • Use for item in lst to visit each current Element.
  • Use item.find("id").text and item.find("name").text for child text.
  • Use item.get("x") for the attribute on the user element.
  1. 1
    Parse the XML into a tree.
  2. 2
    Call findall with the path for the repeating elements.
  3. 3
    Check the returned list length and inspect an item if needed.
  4. 4
    Use a for loop to bind each Element to the loop variable.
  5. 5
    Use find followed by text for child-element content.
  6. 6
    Use get for an attribute on the current Element.

Key Takeaways

  1. 1
    findall returns a Python list of every XML Element matching a path.
  2. 2
    A for loop visits the returned Elements one at a time, with the loop variable holding the current node.
  3. 3
    Use find(child_name).text to read text from a child element.
  4. 4
    Use get(attribute_name) to read an attribute from the current Element.
  5. 5
    When extraction fails, check the list length, inspect an item, and verify names and paths exactly.

At a glance

  • findall gathers all matching XML nodes into a Python list.
  • The for loop processes each matching Element separately.
  • Child text is accessed with find followed by text.
  • Attributes are accessed with get on the current Element.
  • Debugging begins by checking what findall returned and whether names match the XML exactly.

Related concepts

More concepts starting with E