Browse Source

Fix xmlns attributes properly

split-manual
J. King 3 years ago
parent
commit
d53b9237c4
  1. 8
      lib/DOM/Document.php
  2. 20
      lib/DOM/Element.php
  3. 10
      lib/TreeBuilder.php

8
lib/DOM/Document.php

@ -50,19 +50,15 @@ class Document extends \DOMDocument {
public function createAttributeNS($namespaceURI, $qualifiedName) {
try {
$out = @parent::createAttributeNS($namespaceURI, $qualifiedName);
return parent::createAttributeNS($namespaceURI, $qualifiedName);
} catch (\DOMException $e) {
// The element name is invalid for XML
// Replace any offending characters with "UHHHHHH" where H are the
// uppercase hexadecimal digits of the character's code point
$this->mangledAttributes = true;
$qualifiedName = $this->coerceName($qualifiedName);
$out = parent::createAttributeNS($namespaceURI, $qualifiedName);
return parent::createAttributeNS($namespaceURI, $qualifiedName);
}
if ($out === false) {
throw new \DOMException("Document element must be inserted first");
}
return $out;
}
public function createElement($name, $value = "") {

20
lib/DOM/Element.php

@ -76,20 +76,30 @@ class Element extends \DOMElement {
// set it.
if ($qualifiedName === 'class' && $namespaceURI === null && $this->_classList !== null) {
$this->_classList->value = $value;
} elseif ($namespaceURI === Parser::XMLNS_NAMESPACE) {
// NOTE: We create attribute nodes so that xmlns attributes
// don't get lost; otherwise they cannot be serialized
$a = @$this->ownerDocument->createAttributeNS($namespaceURI, $qualifiedName);
if ($a === false) {
// The document element does not exist yet, so we need
// to insert this element into the document
$this->ownerDocument->appendChild($this);
$a = $this->ownerDocument->createAttributeNS($namespaceURI, $qualifiedName);
$this->ownerDocument->removeChild($this);
}
$a->value = $this->escapeString($value, true);
$this->appendChild($a);
} else {
try {
// NOTE: We create attribute nodes so that xmlns attributes don't get lost
$a = $this->ownerDocument->createAttributeNS($namespaceURI, $qualifiedName);
parent::setAttributeNS($namespaceURI, $qualifiedName, $value);
} catch (\DOMException $e) {
// The attribute name is invalid for XML
// Replace any offending characters with "UHHHHHH" where H are the
// uppercase hexadecimal digits of the character's code point
$this->ownerDocument->mangledAttributes = true;
$qualifiedName = $this->coerceName($qualifiedName);
$a = $this->ownerDocument->createAttributeNS($namespaceURI, $qualifiedName);
parent::setAttributeNS($namespaceURI, $qualifiedName, $value);
}
$a->value = $this->escapeString($value, true);
$this->appendChild($a);
if ($qualifiedName === "id" && $namespaceURI === null) {
$this->setIdAttribute($qualifiedName, true);
}

10
lib/TreeBuilder.php

@ -4150,12 +4150,6 @@ class TreeBuilder {
# Let element be the result of creating an element given document,
# localName, given namespace, null, and is.
$element = $this->DOM->createElementNS($namespace, $token->name);
// DEVIATION: If there is no document (root) element yet, temporarily
// insert this element so that creating attributes for it does not
// fail due to a PHP DOM limitation
if (!$this->DOM->documentElement) {
$this->DOM->appendChild($element);
}
# Append each attribute in the given token to element.
foreach ($token->attributes as $attr) {
# If element has an xmlns attribute in the XMLNS namespace whose value
@ -4174,10 +4168,6 @@ class TreeBuilder {
$element->setAttributeNS($attr->namespace, $attr->name, $attr->value);
}
}
if ($this->DOM->documentElement && $this->DOM->documentElement->isSameNode($element)) {
// Pop off the document element if it was inserted above
$this->DOM->removeChild($element);
}
# Return element.
return $element;
}

Loading…
Cancel
Save