Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.

Use a parser that reports source locations while it reads the XML. For a malformed document, get the line and column from the parser’s exception. To locate an element in valid XML, capture the parser’s location during the relevant event. A regular DOM document or XPath query does not universally preserve where a node appeared in the original file.

The exact API depends on your language and parser. Also, a reported column may be the parser’s current position or the end of an event—not necessarily the opening angle bracket of a tag.

First decide which location you need

There are three different tasks that are often described as “finding the XML line number”:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
  • Finding a syntax error: Catch the parser’s error and report its line and column.
  • Locating an element in valid XML: Use a streaming parser or parser-specific source-location metadata, and save the coordinates as the parser encounters the element.
  • Locating a node already in memory: Check whether the parser retained source locations. Ordinary DOM APIs do not guarantee this; if the information was discarded during parsing, it generally cannot be reconstructed reliably from the node alone.

For an exact byte or character offset—for example, to place a cursor in an editor—use a parser that explicitly exposes offsets or pair parsing with a source-aware scanner. A line and column are parser coordinates, not necessarily visual screen coordinates.

Quick reference

Language or parser How to read the location
Java SAX Locator.getLineNumber() and getColumnNumber() in a callback
.NET XmlReader Cast to IXmlLineInfo; check HasLineInfo(), then read LineNumber and LinePosition
Python Expat CurrentLineNumber and CurrentColumnNumber in a callback
Apple Foundation XMLParser.lineNumber and columnNumber

Most APIs count the first line and first column as 1, but verify the behavior of your parser. Record the filename or system identifier separately: coordinates alone do not identify which source file they refer to.

Java: capture locations with SAX

SAX supplies a Locator through setDocumentLocator. Read it while handling an event, and copy the numbers if you need them later.

import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.Attributes;
import org.xml.sax.Locator;
import org.xml.sax.helpers.DefaultHandler;

var factory = SAXParserFactory.newInstance();
var parser = factory.newSAXParser();

var handler = new DefaultHandler() {
    private Locator locator;

    @Override
    public void setDocumentLocator(Locator locator) {
        this.locator = locator;
    }

    @Override
    public void startElement(String uri, String localName,
                             String qualifiedName, Attributes attributes) {
        System.out.printf("%s at line %d, column %d%n",
            qualifiedName,
            locator.getLineNumber(),
            locator.getColumnNumber());
    }
};

parser.parse("input.xml", handler);

The callback is where the location applies. The SAX locator documentation says its values are valid only during the callback and may be unavailable (reported as -1). Copy the line and column into your own record in startElement, characters, or whichever callback matches what you are locating. SAX’s coordinate describes the current event’s position and is an approximation; do not assume it identifies the first character of the opening tag. See the Java SAX Locator documentation.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Rank #2
Sale
XML in a Nutshell, Third Edition
  • Used Book in Good Condition

Java: report a malformed-document location

import java.io.File;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.SAXParseException;
import org.xml.sax.helpers.DefaultHandler;

var parser = SAXParserFactory.newInstance().newSAXParser();
try {
    parser.parse(new File("input.xml"), new DefaultHandler());
} catch (SAXParseException e) {
    System.err.printf("XML error at line %d, column %d: %s%n",
        e.getLineNumber(), e.getColumnNumber(), e.getMessage());
}

.NET: use IXmlLineInfo

XmlReader is a streaming reader. Its current location can be obtained through IXmlLineInfo; check HasLineInfo() instead of assuming every reader supplies coordinates.

using System;
using System.Xml;

using var reader = XmlReader.Create("input.xml");
var lineInfo = reader as IXmlLineInfo;

while (reader.Read())
{
    if (lineInfo?.HasLineInfo() == true)
    {
        Console.WriteLine(
            $"{reader.NodeType} {reader.Name} at line " +
            $"{lineInfo.LineNumber}, position {lineInfo.LinePosition}");
    }
}

LinePosition is the column-like value in this API. It describes the reader’s current parsing state or node; it is not a universal guarantee of the tag’s opening-character position. For malformed XML, catch XmlException:

try
{
    using var reader = XmlReader.Create("input.xml");
    while (reader.Read()) { }
}
catch (XmlException ex)
{
    Console.WriteLine(
        $"XML error at line {ex.LineNumber}, " +
        $"position {ex.LinePosition}: {ex.Message}");
}

See Microsoft’s IXmlLineInfo reference. If you load XML into LINQ to XML and need line details afterward, enable the relevant line-information retention option when loading, where supported; projecting nodes into unrelated application objects can lose that metadata.

Python: use Expat callbacks

Python’s standard Expat parser exposes its current position during callbacks. This is useful when processing valid XML and recording where each start tag was encountered.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
from xml.parsers import expat

parser = expat.ParserCreate()

def start_element(name, attrs):
    print(
        f"{name} at line {parser.CurrentLineNumber}, "
        f"column {parser.CurrentColumnNumber}"
    )

parser.StartElementHandler = start_element

with open("input.xml", "rb") as xml_file:
    parser.ParseFile(xml_file)

For malformed XML, Expat raises ExpatError, which includes the error line and offset:

from xml.parsers import expat

parser = expat.ParserCreate()
try:
    with open("input.xml", "rb") as xml_file:
        parser.ParseFile(xml_file)
except expat.ExpatError as error:
    print(
        f"XML error at line {error.lineno}, "
        f"column {error.offset}: {error}"
    )

See the Python pyexpat documentation. xml.etree.ElementTree is convenient for tree processing, but it is not a general interface for retrieving the original line and column of every node. Use Expat callbacks or a library that retains source locations when you need them.

Swift: use Apple Foundation’s XMLParser

In an XMLParserDelegate callback, read the parser’s line and column properties alongside the element details. The parser also exposes these values when reporting an error.

import Foundation

final class Handler: NSObject, XMLParserDelegate {
    func parser(_ parser: XMLParser,
                didStartElement elementName: String,
                namespaceURI: String?,
                qualifiedName qName: String?,
                attributes attributeDict: [String: String] = [:]) {
        print("(elementName) at line (parser.lineNumber), " +
              "column (parser.columnNumber)")
    }

    func parser(_ parser: XMLParser, parseErrorOccurred error: Error) {
        print("XML error at line (parser.lineNumber), " +
              "column (parser.columnNumber): (error)")
    }
}

See Apple’s references for lineNumber and columnNumber. As with other streaming APIs, interpret the coordinates according to the parser’s current event and state.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Why a DOM or XPath query may not give the answer

A DOM represents XML as a tree: elements, attributes, text, and relationships. The XML data model does not require every DOM implementation to expose original source coordinates. A parser may offer optional line metadata, but an ordinary DOM element is not guaranteed to have a line or column property. XPath selects nodes logically; it does not inherently reveal where those nodes appeared in the source.

Best Value
Sale

If you still control parsing, save a record when the parser encounters the node—for example, source identifier, element name, namespace URI, line, column, and node type—and associate it with your application object. If the XML is already in a DOM without location metadata, searching the original file for a tag name is only a fragile fallback: names repeat, namespaces alter names, and comments, CDATA, entities, or formatting can make a text search misleading. Re-serializing the DOM is not a fix; serialization can change whitespace and line breaks.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

How to interpret coordinates and edge cases

  • Event position versus tag start: A streaming parser may report the cursor, the end of an event, or another parser-defined position. A tag split across lines, such as <item followed by separate attribute lines, makes assumptions about a single “element column” especially risky.
  • Error position versus mistake origin: The location usually tells you where the parser detected a problem. A missing quote or unclosed construct may only become detectable several characters or lines after the original mistake.
  • Column versus visual editor position: Tabs may display as several spaces. Encodings, Unicode code units, combining marks, and wide characters can also make parser columns differ from what an editor shows. Java SAX, for example, defines columns as a one-based count of Java char values since the last line ending and describes the value as approximate.
  • Entities and external sources: With internal entity expansion, an external parsed entity, schemas, or included resources, the relevant source may not be the main XML file. Depending on the parser, a location may refer to a reference, expanded input, or entity-specific source. Include the filename or system identifier when available. Java SAX cautions that entity expansion and complex Unicode can affect location accuracy.
  • Namespaces: Capture location in the same event where you obtain the qualified name, local name, and namespace URI. A name such as book:item may be reported with its prefix, local name item, and a separate namespace URI; the location belongs to the source event.
  • Newlines and offsets: Line-ending normalization and the parser’s character representation matter. A UTF-8 byte offset is not the same thing as a character column. If an editor integration needs exact source placement, prefer a parser with explicit source offsets and test it against your input encoding and newline styles.

Choose the approach that matches the job

Need Recommended approach
Diagnose malformed XML Catch the parser’s exception and report its line, column or position, and source identifier.
Track elements in a large file Use a streaming parser and store coordinates during callbacks or reader events.
Query a tree later Use a parser or load option that explicitly retains line information, then verify it is available on the nodes.
Preserve exact source formatting or offsets Use a source-preserving or offset-aware parser; a conventional DOM is designed for structure, not exact lexical preservation.
Find a node with XPath Retain source locations during parsing; XPath alone cannot recover them.

DOM is convenient for navigation and modification but often costs more memory and may omit source layout. SAX is low-memory and provides an explicit locator, but it is forward-only and callback-driven. Pull readers such as .NET’s XmlReader or Java StAX give more control over event processing, but their coordinates still belong to the current event and should be saved before advancing.

Troubleshooting checklist

  1. Identify the parser and whether you need an error location, an event location, or a previously loaded node’s location.
  2. For errors, read the parser-specific exception. For valid XML, use a callback or reader that exposes locations.
  3. Check whether location reporting is available; in .NET, call HasLineInfo().
  4. Copy coordinates while handling the relevant event instead of relying on a parser cursor later.
  5. Do not assume a coordinate marks the opening angle bracket, is zero-based, or matches an editor’s visual column.
  6. Test one-line and indented XML, multiline attributes, namespaces, Unicode, comments, CDATA, and malformed markup.
  7. Report a filename or system identifier with the coordinates, especially when external entities or other XML sources are involved.

The dependable pattern is to parse with location reporting enabled, capture the parser’s position at the moment it encounters the relevant event, and preserve that information if it must survive beyond parsing.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Quick Recap

SaleBestseller No. 2
XML in a Nutshell, Third Edition
XML in a Nutshell, Third Edition
Used Book in Good Condition
$16.57
Bestseller No. 3
Bestseller No. 4
SaleBestseller No. 5
XML All-in-One Desk Reference For Dummies
XML All-in-One Desk Reference For Dummies
Used Book in Good Condition
$18.98

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.