Skip to content

Fix GH-11500: Namespace reuse in createElementNS() generates wrong output #11528

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from

Conversation

nielsdos
Copy link
Member

When you construct a DOM tree containing subtrees which are constructed top-down, this won't remove the redundant namespaces. That's because the following conditions hold:

  1. The namespace are reused from the doc->oldNs list.
  2. Therefore during reconciliation no nsDef field is set, so no redundant
    namespaces are removed by our reconciliation code.

Furthermore, it would only be fixed up automatically if the tree wasn't added in bottom-up way, or if it had been constructed bottom-up from the start.

Fix it by setting a flag to remove redundant namespaces in the libxml2 reconciliation call.
Since removing redundant namespaces may have a performance cost, we only do this after performing a simple check.

Closes GH-11500

… output

When you construct a DOM tree containing subtrees which are constructed
top-down, this won't remove the redundant namespaces. That's because the
following conditions hold:
1) The namespace are reused from the doc->oldNs list.
2) Therefore during reconciliation no nsDef field is set, so no redundant
   namespaces are removed by our reconciliation code.

Furthermore, it would only be fixed up automatically if the tree wasn't
added in bottom-up way, or if it had been constructed bottom-up from the
start.

Fix it by setting a flag to remove redundant namespaces in the libxml2
reconciliation call.
Since removing redundant namespaces may have a performance cost, we only do
this after performing a simple check.
@nielsdos
Copy link
Member Author

Forgot to split the commits up in a before and after. Here's the diff as a gist, the removed lines are the old behaviour and the green lines the new behaviour https://gist.github.com/nielsdos/40d26d1df9339ab974f027f8c8ff82a5

Copy link
Member

@Girgias Girgias left a comment

Choose a reason for hiding this comment

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

LGTM

@@ -1494,7 +1494,8 @@ static void dom_libxml_reconcile_ensure_namespaces_are_declared(xmlNodePtr nodep
* Although libxml2 currently does not use this for the reconciliation, it still
* makes sense to do this just in case libxml2's internal change in the future. */
xmlDOMWrapCtxt dummy_ctxt = {0};
xmlDOMWrapReconcileNamespaces(&dummy_ctxt, nodep, /* options */ 0);
bool remove_redundant = nodep->nsDef == NULL && nodep->ns != NULL;
xmlDOMWrapReconcileNamespaces(&dummy_ctxt, nodep, /* options */ remove_redundant ? (1 << 0) : 0);
Copy link
Member

Choose a reason for hiding this comment

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

Should the (1 << 0) be exposed as a constant somewhere?

Copy link
Member Author

Choose a reason for hiding this comment

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

Sadly libxml2 doesn't have a define for this. I can make my own define (but with a PHP_LIBXML2_ prefix to prevent name collisions). I'll do that in the merge.

@nielsdos nielsdos closed this in 961e57e Jun 26, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Namespace reuse in createElementNS() generates wrong output
2 participants