Index: Include/pyexpat.h =================================================================== --- Include/pyexpat.h (revision 51208) +++ Include/pyexpat.h (working copy) @@ -42,6 +42,9 @@ XML_Parser parser, XML_UnknownEncodingHandler handler, void *encodingHandlerData); void (*SetUserData)(XML_Parser parser, void *userData); + XML_Size (*GetCurrentLineNumber)(XML_Parser parser); + XML_Size (*GetCurrentColumnNumber)(XML_Parser parser); + XML_Index (*GetCurrentByteIndex)(XML_Parser); /* always add new stuff to the end! */ }; Index: Lib/test/test_xml_etree_c.py =================================================================== --- Lib/test/test_xml_etree_c.py (revision 51208) +++ Lib/test/test_xml_etree_c.py (working copy) @@ -204,6 +204,17 @@ "" % encoding ) +def check_xml_file_positioning(): + """ + >>> xb = ET.XMLTreeBuilder() + >>> xb.CurrentLineNumber + 1 + >>> xb.CurrentColumnNumber + 0 + >>> xb.CurrentByteIndex + -1 + """ + def test_main(): from test import test_xml_etree_c test_support.run_doctest(test_xml_etree_c, verbosity=True) Index: Modules/pyexpat.c =================================================================== --- Modules/pyexpat.c (revision 51208) +++ Modules/pyexpat.c (working copy) @@ -2050,6 +2050,9 @@ capi.SetProcessingInstructionHandler = XML_SetProcessingInstructionHandler; capi.SetUnknownEncodingHandler = XML_SetUnknownEncodingHandler; capi.SetUserData = XML_SetUserData; + capi.GetCurrentLineNumber = XML_GetCurrentLineNumber; + capi.GetCurrentColumnNumber = XML_GetCurrentColumnNumber; + capi.GetCurrentByteIndex = XML_GetCurrentByteIndex; /* export as cobject */ capi_object = PyCObject_FromVoidPtr(&capi, NULL); Index: Modules/_elementtree.c =================================================================== --- Modules/_elementtree.c (revision 51208) +++ Modules/_elementtree.c (working copy) @@ -2574,6 +2574,19 @@ sprintf(buffer, "Expat %d.%d.%d", XML_MAJOR_VERSION, XML_MINOR_VERSION, XML_MICRO_VERSION); return PyString_FromString(buffer); + } else if (name[0] == 'C') { + /* taken (almost) verbatim from pyexpat.c. */ + if (strcmp(name, "CurrentLineNumber") == 0) + return PyInt_FromLong((long) + EXPAT(GetCurrentLineNumber)(self->parser)); + if (strcmp(name, "CurrentColumnNumber") == 0) + return PyInt_FromLong((long) + EXPAT(GetCurrentColumnNumber)(self->parser)); + if (strcmp(name, "CurrentByteIndex") == 0) + return PyInt_FromLong((long) + EXPAT(GetCurrentByteIndex)(self->parser)); + PyErr_SetString(PyExc_AttributeError, name); + return NULL; } else { PyErr_SetString(PyExc_AttributeError, name); return NULL;