GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — gh-149468: Add option to validate ElementTree during serialization by serhiy-storchaka · Pull Request #149469 · python/cpython

Conversation

@serhiy-storchaka

@serhiy-storchaka serhiy-storchaka commented May 6, 2026 •
edited by bedevere-app Bot
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Member
  • Issue: Add option to validate ElementTree during serialization #149468

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@serhiy-storchaka
serhiy-storchaka requested a review from AA-Turner as a code owner May 6, 2026 19:25
@bedevere-app bedevere-app Bot mentioned this pull request May 6, 2026
Add option to validate ElementTree during serialization #149468
Open
@bedevere-app bedevere-app Bot added the awaiting core review label May 6, 2026
@serhiy-storchaka

serhiy-storchaka commented May 6, 2026

Copy link
Copy Markdown
Member Author

This PR also fixes some bugs in serialization to HTML. I am going to extract them into separate issue before merging this PR. But for now, it is more convenient to review them together.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

sethmlarson
sethmlarson reviewed May 6, 2026
View reviewed changes
Comment thread Misc/NEWS.d/next/Library/2026-05-06-22-22-05.gh-issue-149468.IUSCzU.rst Outdated
@@ -0,0 +1,3 @@
Add the *validate* option to :mod:`xml.etree.ElementTree` serialization
functions, which allows to validate the element or element tree before

@sethmlarson sethmlarson May 6, 2026 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Contributor

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion on wording: "...which validates the element or element tree names and values only contain allowed/escaped characters prior to serialization"

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@serhiy-storchaka serhiy-storchaka May 31, 2026

Copy link
Copy Markdown
Member Author

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, this is not good. Characters should not be escaped prior to serialization. Element tree has no names, I wrote "the element or element tree" because some methods/functions serialize an element, and others work with the element tree. We check not only for invalid characters, but for invalid sequences of characters, and some characters/sequences can only be invalid at the start or the end of the name or content.

I updated the entry according to description proposed by @ezio-melotti.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
merwok
merwok reviewed May 6, 2026
View reviewed changes
Comment thread Lib/xml/etree/ElementTree.py Resolved

Uh oh!

There was an error while loading. Please reload this page.

@serhiy-storchaka
serhiy-storchaka requested review from a team, FFY00, ZeroIntensity, corona10, emmatyping, encukou, ericsnowcurrently and erlend-aasland as code owners May 7, 2026 17:18
serhiy-storchaka added 2 commits May 7, 2026 20:21
@serhiy-storchaka
pythongh-149489: Fix ElementTree serialization to HTML
e41d61c
* The content of comments, processing instructions and elements "xmp",
  "iframe", "noembed", "noframes", and "plaintext" is no longer escaped.
* The "plaintext" element no longer have the closing tag.
* Add support of empty attributes (with value None).
@serhiy-storchaka
pythongh-149468: Add option to validate ElementTree during serialization
a134c0b
@serhiy-storchaka
serhiy-storchaka force-pushed the xml-etree-validate branch from 73e1b24 to a134c0b Compare May 7, 2026 17:26
@serhiy-storchaka

serhiy-storchaka commented May 7, 2026

Copy link
Copy Markdown
Member Author

Rebased it onto #149490.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

vstinner
vstinner reviewed May 13, 2026
View reviewed changes
Comment thread Doc/whatsnew/3.15.rst Resolved

Uh oh!

There was an error while loading. Please reload this page.

@ned-deily
ned-deily removed the request for review from a team May 16, 2026 04:55
@serhiy-storchaka
Merge branch 'main' into xml-etree-validate
c81fe70
@serhiy-storchaka
serhiy-storchaka force-pushed the xml-etree-validate branch from ca19970 to c81fe70 Compare May 29, 2026 21:42
ezio-melotti
ezio-melotti reviewed May 30, 2026
View reviewed changes
Comment thread Doc/library/xml.etree.elementtree.rst Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread Doc/library/xml.etree.elementtree.rst Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread Doc/library/xml.etree.elementtree.rst Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread Doc/library/xml.etree.elementtree.rst Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread Lib/test/test_xml_etree.py Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread Lib/test/test_xml_etree.py Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread Lib/test/test_xml_etree.py Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread Lib/xml/etree/ElementTree.py Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread Lib/xml/etree/ElementTree.py
if text:
if validate:
if '\0' in text:
raise ValueError('invalid characters')

@ezio-melotti ezio-melotti May 30, 2026

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
raise ValueError('invalid characters')
raise ValueError('invalid character ("\\0")')

Similarly the other error messages could specify what is invalid.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@serhiy-storchaka serhiy-storchaka May 31, 2026

Copy link
Copy Markdown
Member Author

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We perhaps should also forbid the surrogate codes. They are not explicitly mentioned in the tokenizer definition, unlike to the null character, but they are invalid in all standard encodings, and using numeric references for them is also invalid (https://html.spec.whatwg.org/multipage/parsing.html#numeric-character-reference-end-state).

As for what invalid, it is not always easily accessible. xml.is_valid_name() and xml.is_valid_text() simply return a boolean.

We could include the name of the parent element, but this may complicate the code to handle special cases of undefined or None.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@serhiy-storchaka @ezio-melotti
Apply suggestions from code review
ea414fa
Co-authored-by: Ezio Melotti <[email protected]>
serhiy-storchaka
serhiy-storchaka commented May 31, 2026
View reviewed changes

@serhiy-storchaka serhiy-storchaka left a comment

Copy link
Copy Markdown
Member Author

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for your review @ezio-melotti. See also the issue. "XML validation" has its own specific meaning, so there is a question about using the name "validate" for our much more lenient checks.

We do not check that the output is well-formed. There are much more strict rules for what the name of the element or attribute should be. I use the rules of the HTML parser, which accepts much more.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Comment thread Doc/library/xml.etree.elementtree.rst Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread Lib/test/test_xml_etree.py Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread Lib/xml/etree/ElementTree.py Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread Lib/xml/etree/ElementTree.py
if text:
if validate:
if '\0' in text:
raise ValueError('invalid characters')

@serhiy-storchaka serhiy-storchaka May 31, 2026

Copy link
Copy Markdown
Member Author

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We perhaps should also forbid the surrogate codes. They are not explicitly mentioned in the tokenizer definition, unlike to the null character, but they are invalid in all standard encodings, and using numeric references for them is also invalid (https://html.spec.whatwg.org/multipage/parsing.html#numeric-character-reference-end-state).

As for what invalid, it is not always easily accessible. xml.is_valid_name() and xml.is_valid_text() simply return a boolean.

We could include the name of the parent element, but this may complicate the code to handle special cases of undefined or None.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
serhiy-storchaka added 4 commits May 31, 2026 11:46
@serhiy-storchaka
Merge branch 'main' into xml-etree-validate
452480d
@serhiy-storchaka
Add more tests for processing instructions
474411f
@serhiy-storchaka
Add more details in exceptions.
22e5543
@serhiy-storchaka
Check also for surrogates in HTML.
e12e88d
serhiy-storchaka added 2 commits May 31, 2026 14:16
@serhiy-storchaka
Move the What's New entry to 3.16.
8cc34e7
@serhiy-storchaka
Update the NEWS entry.
3d0fdd2
@read-the-docs-community

read-the-docs-community Bot commented May 31, 2026 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown

Documentation build overview

📚 cpython-previews | 🛠️ Build #34538384 | 📁 Comparing 0fcb148 against main (350e9de)

  🔍 Preview build  

435 files changed · + 14 added · ± 419 modified · - 2 deleted

+ Added

  • builtins/constants.html
  • builtins/exceptions.html
  • builtins/functions.html
  • builtins/index.html
  • builtins/stdtypes.html
  • builtins/threadsafety.html
  • builtins/time-complexity.html
  • howto/abi3t-migration.html
  • library/asyncio-threading.html
  • library/asyncio-tools.html
  • and 4 more...

± Modified

  • bugs.html
  • glossary.html
  • index.html
  • license.html
  • py-modindex.html
  • c-api/arg.html
  • c-api/bool.html
  • c-api/buffer.html
  • c-api/bytearray.html
  • c-api/bytes.html
  • and 409 more...

- Deleted

  • library/asyncio-policy.html
  • library/dialog.html
All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

vstinner
vstinner reviewed Jun 1, 2026
View reviewed changes
Comment thread Doc/library/xml.etree.elementtree.rst Outdated
.. function:: tostring(element, encoding="us-ascii", method="xml", *, \
xml_declaration=None, default_namespace=None, \
short_empty_elements=True)
validate=False, short_empty_elements=True)

@vstinner vstinner Jun 1, 2026

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Usually new parameters are added to the end, so the order gives an idea when a parameter was added. Why not putting it at the end? (It only matters for the documentation.)

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@serhiy-storchaka serhiy-storchaka Jun 1, 2026

Copy link
Copy Markdown
Member Author

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If all parameters was keyword-only, I would place method and validate before other options, because they are more general and important. But keyword-or-positional parameters should keep their position, so I can only change order of validate and short_empty_elements.

Your arguments are also valid. I'll, change the order.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Comment thread Doc/library/xml.etree.elementtree.rst
like ``<script>`` do not contain illegal sequences according
to the selected *method* (``"xml"`` or ``"html"``).
Raise :exc:`ValueError` if any check fails.
By default, or if *method* is ``"text"``, no validation is performed.

@vstinner vstinner Jun 1, 2026

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand method="text" case. Does it force validate to False? How is it different from the default behavior (validate=False)?

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@serhiy-storchaka serhiy-storchaka Sep 3, 2026

Copy link
Copy Markdown
Member Author

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

validate has no effect for method="text".

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Comment thread Lib/xml/etree/ElementTree.py
if tag is Comment:
if validate:
if '--' in text or text.endswith('-') or not is_valid_text(text):
raise ValueError('invalid comment')

@vstinner vstinner Jun 1, 2026

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"invalid comment" error can be raised in 3 very different cases. Would it be possible to give the reason in the error message? For example: "invalid comment: illegal character U+0000". Same remark for _serialize_html().

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@serhiy-storchaka serhiy-storchaka Jun 1, 2026

Copy link
Copy Markdown
Member Author

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We do not know what character is invalid. We need to reimplement is_valid_text and is_valid_name to get such information.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Comment thread Lib/xml/etree/ElementTree.py
_serialize_html(write, e, qnames, None, validate=validate)
else:
if validate:
if not re.fullmatch('[A-Za-z][^\0\t\n\r\f />\ud800-\udfff]*+', tag):

@vstinner vstinner Jun 1, 2026

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the purpose of + in [range]*+? Why not just writing [range]*?

Similar question on [range]++ below: re.fullmatch('[^\0\t\n\r\f />=\ud800-\udfff]++', k).

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@serhiy-storchaka serhiy-storchaka Jun 1, 2026

Copy link
Copy Markdown
Member Author

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Microoptimization. It disables backtracking.

For for example, we check the name "a0123456789/". The RE engine first matches prefix "a0123456789", but this is not the entire string, it backtracks:

  • prefix "a012345678" matches, is this the entire string?
  • prefix "a01234567" matches, is this the entire string?
  • prefix "a01234567" matches, is this the entire string?
  • ...

We perhaps can make the RE engine smarter and automatically detect such pattern, but this is a separate issue.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Comment thread Lib/xml/etree/ElementTree.py
try:
if validate:
if not is_valid_text(text):
raise ValueError('invalid characters')

@vstinner vstinner Jun 1, 2026

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be possible to mention the first invalid character in the error message? Otherwise, it can be tricky to debug such issue.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@serhiy-storchaka serhiy-storchaka Jun 1, 2026

Copy link
Copy Markdown
Member Author

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To do this, we need to murder is_valid_text and pull his insides out.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@merwok merwok Sep 3, 2026

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or have is_valid_text / new function validate_text raise the exception directly.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@serhiy-storchaka serhiy-storchaka Sep 3, 2026

Copy link
Copy Markdown
Member Author

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be done in a following issue, after we get more examples of its use.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
This was referenced Sep 1, 2026
gh-57092: Add the validate option to xml.sax.saxutils.XMLGenerator #156800
Open
xml.sax.xmlreader.AttributesImpl allows empty string as attribute names #57092
Open
serhiy-storchaka added 4 commits September 3, 2026 13:31
@serhiy-storchaka
Merge remote-tracking branch 'upstream/main' into xml-etree-validate
0a7c117
# Conflicts:
#	Doc/library/xml.etree.elementtree.rst
#	Doc/whatsnew/3.16.rst
#	Lib/xml/etree/ElementTree.py
@serhiy-storchaka
Rename the error message to "invalid namespace prefix"
2b67e17
The checked name is a prefix, not a namespace name, which is the URI.
@serhiy-storchaka
Use subTests in the validation tests
e2ab82e
The tests are parametrized by strings, and QName instances are created in the
body, so nothing needs the module at class definition time.  In the HTML
tests the sets of the invalid string values and the invalid QName values are
different, so such tests are split.
@serhiy-storchaka
Merge remote-tracking branch 'upstream/main' into xml-etree-validate
0fcb148
# Conflicts:
#	Doc/whatsnew/3.16.rst
#	Lib/xml/etree/ElementTree.py
@serhiy-storchaka serhiy-storchaka mentioned this pull request Nov 11, 2026
xml.dom.minidom: serializing a comment ending in '-' silently produces non-well-formed XML #156812
Open
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

@vstinner vstinner vstinner left review comments
@merwok merwok merwok left review comments
@sethmlarson sethmlarson sethmlarson left review comments
@ezio-melotti ezio-melotti ezio-melotti left review comments
@AA-Turner AA-Turner Awaiting requested review from AA-Turner AA-Turner is a code owner
@ericsnowcurrently ericsnowcurrently Awaiting requested review from ericsnowcurrently
@ZeroIntensity ZeroIntensity Awaiting requested review from ZeroIntensity
@FFY00 FFY00 Awaiting requested review from FFY00
@encukou encukou Awaiting requested review from encukou
@erlend-aasland erlend-aasland Awaiting requested review from erlend-aasland
@corona10 corona10 Awaiting requested review from corona10
@emmatyping emmatyping Awaiting requested review from emmatyping

Uh oh!

There was an error while loading. Please reload this page.

Assignees

No one assigned

Labels

awaiting core review

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

Uh oh!

There was an error while loading. Please reload this page.

5 participants

@serhiy-storchaka @vstinner @merwok @sethmlarson @ezio-melotti
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.