Skip to content
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

fix: ensure namespaced attributes are reparented properly #2230

Merged
merged 5 commits into from May 11, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
26 changes: 21 additions & 5 deletions CHANGELOG.md
Expand Up @@ -6,20 +6,36 @@ Nokogiri follows [Semantic Versioning](https://semver.org/), please see the [REA

## next / unreleased

### Dependencies
### Added

__HTML5 support__ has been added (to CRuby only) by merging [Nokogumbo](https://github.com/rubys/nokogumbo) into Nokogiri. The Nokogumbo public API has been preserved, so this functionality is available under the `Nokogiri::HTML5` namespace. [[#2204](https://github.com/sparklemotion/nokogiri/issues/2204)]

Please note that HTML5 support is not available for JRuby in this version. However, we feel it is important to think about JRuby and we hope to work on this in the future. If you're interested in helping with HTML5 support on JRuby, please reach out to the maintainers by commenting on issue [#2227](https://github.com/sparklemotion/nokogiri/issues/2227).

* [MRI] Upgrade mini_portile2 dependency from `~> 2.5.0` to `~> 2.5.1`.
Please also note that the `Nokogiri::HTML` parse methods still use libxml2's HTML4 parser in the v1.12 release series. Future releases of Nokogiri may change this behavior, but we'll proceed cautiously to avoid breaking existing applications.

Many thanks to Sam Ruby, Steve Checkoway, and Craig Barnes for creating and maintaining Nokogumbo and supporting the Gumbo HTML5 parser. They're now Nokogiri core contributors with all the powers and privileges pertaining thereto. 🙌


### Changed

* Introduce `Nokogiri::XML::ParseOptions::DEFAULT_XSLT` which adds the libxslt-preferred options of `NOENT | DTDLOAD | DTDATTR | NOCDATA` to `ParseOptions::DEFAULT_XML`.
* `Nokogiri.XSLT` parses the stylesheet using `ParseOptions::DEFAULT_XSLT`, which should make some edge-case XSL transformations match libxslt's default behavior. [[#1940](https://github.com/sparklemotion/nokogiri/issues/1940)]
* Introduce a new constant, `Nokogiri::XML::ParseOptions::DEFAULT_XSLT`, which adds the libxslt-preferred options of `NOENT | DTDLOAD | DTDATTR | NOCDATA` to `ParseOptions::DEFAULT_XML`.
* `Nokogiri.XSLT` parses stylesheets using `ParseOptions::DEFAULT_XSLT`, which should make some edge-case XSL transformations match libxslt's default behavior. [[#1940](https://github.com/sparklemotion/nokogiri/issues/1940)]


### Fixed

* [CRuby] Namespaced attributes are handled properly when their parent node is reparented into another document. Previously, the namespace may have gotten dropped. [[#2228](https://github.com/sparklemotion/nokogiri/issues/2228)]


### Improved

* [MRI] Speed up (slightly) the compile time of packaged libraries `libiconv`, `libxml2`, and `libxslt` by using autoconf's `--disable-dependency-tracking` option.
* [CRuby] Speed up (slightly) the compile time of packaged libraries `libiconv`, `libxml2`, and `libxslt` by using autoconf's `--disable-dependency-tracking` option. ("ruby" platform gem only.)


### Dependencies

* [CRuby] Upgrade mini_portile2 dependency from `~> 2.5.0` to `~> 2.5.1`. ("ruby" platform gem only.)


## 1.11.3 / 2021-04-07
Expand Down
22 changes: 11 additions & 11 deletions ext/java/nokogiri/XmlDocument.java
Expand Up @@ -657,17 +657,17 @@ private static class DocumentBuilderFactoryHolder
}
String algorithmURI = null;
switch (mode) {
case 0: // XML_C14N_1_0
if (with_comments) { algorithmURI = Canonicalizer.ALGO_ID_C14N_WITH_COMMENTS; }
else { algorithmURI = Canonicalizer.ALGO_ID_C14N_OMIT_COMMENTS; }
break;
case 1: // XML_C14N_EXCLUSIVE_1_0
if (with_comments) { algorithmURI = Canonicalizer.ALGO_ID_C14N_EXCL_WITH_COMMENTS; }
else { algorithmURI = Canonicalizer.ALGO_ID_C14N_EXCL_OMIT_COMMENTS; }
break;
case 2: // XML_C14N_1_1 = 2
if (with_comments) { algorithmURI = Canonicalizer.ALGO_ID_C14N11_WITH_COMMENTS; }
else { algorithmURI = Canonicalizer.ALGO_ID_C14N11_OMIT_COMMENTS; }
case 0: // XML_C14N_1_0
if (with_comments) { algorithmURI = Canonicalizer.ALGO_ID_C14N_WITH_COMMENTS; }
else { algorithmURI = Canonicalizer.ALGO_ID_C14N_OMIT_COMMENTS; }
break;
case 1: // XML_C14N_EXCLUSIVE_1_0
if (with_comments) { algorithmURI = Canonicalizer.ALGO_ID_C14N_EXCL_WITH_COMMENTS; }
else { algorithmURI = Canonicalizer.ALGO_ID_C14N_EXCL_OMIT_COMMENTS; }
break;
case 2: // XML_C14N_1_1 = 2
if (with_comments) { algorithmURI = Canonicalizer.ALGO_ID_C14N11_WITH_COMMENTS; }
else { algorithmURI = Canonicalizer.ALGO_ID_C14N11_OMIT_COMMENTS; }
}
try {
Canonicalizer canonicalizer = Canonicalizer.getInstance(algorithmURI);
Expand Down
10 changes: 5 additions & 5 deletions ext/java/nokogiri/XmlElementContent.java
Expand Up @@ -142,11 +142,11 @@ public IRubyObject value(Ruby runtime)
right = runtime.getNil();

switch (type) {
case SEQ:
case OR:
applyGroup(runtime, klass, doc, iter);
default:
// noop
case SEQ:
case OR:
applyGroup(runtime, klass, doc, iter);
default:
// noop
}
}

Expand Down
132 changes: 66 additions & 66 deletions ext/java/nokogiri/XmlNode.java
Expand Up @@ -1516,56 +1516,56 @@ public class XmlNode extends RubyObject
{
String type;
switch (node.getNodeType()) {
case Node.ELEMENT_NODE:
if (this instanceof XmlElementDecl) {
type = "ELEMENT_DECL";
} else if (this instanceof XmlAttributeDecl) {
type = "ATTRIBUTE_DECL";
} else if (this instanceof XmlEntityDecl) {
type = "ENTITY_DECL";
} else {
type = "ELEMENT_NODE";
}
break;
case Node.ATTRIBUTE_NODE:
type = "ATTRIBUTE_NODE";
break;
case Node.TEXT_NODE:
type = "TEXT_NODE";
break;
case Node.CDATA_SECTION_NODE:
type = "CDATA_SECTION_NODE";
break;
case Node.ENTITY_REFERENCE_NODE:
type = "ENTITY_REF_NODE";
break;
case Node.ENTITY_NODE:
type = "ENTITY_NODE";
break;
case Node.PROCESSING_INSTRUCTION_NODE:
type = "PI_NODE";
break;
case Node.COMMENT_NODE:
type = "COMMENT_NODE";
break;
case Node.DOCUMENT_NODE:
if (this instanceof HtmlDocument) {
type = "HTML_DOCUMENT_NODE";
} else {
type = "DOCUMENT_NODE";
}
break;
case Node.DOCUMENT_TYPE_NODE:
type = "DOCUMENT_TYPE_NODE";
break;
case Node.DOCUMENT_FRAGMENT_NODE:
type = "DOCUMENT_FRAG_NODE";
break;
case Node.NOTATION_NODE:
type = "NOTATION_NODE";
break;
default:
return context.runtime.newFixnum(0);
case Node.ELEMENT_NODE:
if (this instanceof XmlElementDecl) {
type = "ELEMENT_DECL";
} else if (this instanceof XmlAttributeDecl) {
type = "ATTRIBUTE_DECL";
} else if (this instanceof XmlEntityDecl) {
type = "ENTITY_DECL";
} else {
type = "ELEMENT_NODE";
}
break;
case Node.ATTRIBUTE_NODE:
type = "ATTRIBUTE_NODE";
break;
case Node.TEXT_NODE:
type = "TEXT_NODE";
break;
case Node.CDATA_SECTION_NODE:
type = "CDATA_SECTION_NODE";
break;
case Node.ENTITY_REFERENCE_NODE:
type = "ENTITY_REF_NODE";
break;
case Node.ENTITY_NODE:
type = "ENTITY_NODE";
break;
case Node.PROCESSING_INSTRUCTION_NODE:
type = "PI_NODE";
break;
case Node.COMMENT_NODE:
type = "COMMENT_NODE";
break;
case Node.DOCUMENT_NODE:
if (this instanceof HtmlDocument) {
type = "HTML_DOCUMENT_NODE";
} else {
type = "DOCUMENT_NODE";
}
break;
case Node.DOCUMENT_TYPE_NODE:
type = "DOCUMENT_TYPE_NODE";
break;
case Node.DOCUMENT_FRAGMENT_NODE:
type = "DOCUMENT_FRAG_NODE";
break;
case Node.NOTATION_NODE:
type = "NOTATION_NODE";
break;
default:
return context.runtime.newFixnum(0);
}

return getNokogiriClass(context.runtime, "Nokogiri::XML::Node").getConstant(type);
Expand Down Expand Up @@ -1676,23 +1676,23 @@ protected enum AdoptScheme {
Node parent = thisNode.getParentNode();

switch (scheme) {
case CHILD:
Node[] children = adoptAsChild(thisNode, otherNode);
if (children.length == 1 && otherNode == children[0]) {
case CHILD:
Node[] children = adoptAsChild(thisNode, otherNode);
if (children.length == 1 && otherNode == children[0]) {
break;
} else {
nodeOrTags = nodeArrayToRubyArray(context.runtime, children);
}
break;
case PREV_SIBLING:
adoptAsPrevSibling(context, parent, thisNode, otherNode);
break;
case NEXT_SIBLING:
adoptAsNextSibling(context, parent, thisNode, otherNode);
break;
case REPLACEMENT:
adoptAsReplacement(context, parent, thisNode, otherNode);
break;
} else {
nodeOrTags = nodeArrayToRubyArray(context.runtime, children);
}
break;
case PREV_SIBLING:
adoptAsPrevSibling(context, parent, thisNode, otherNode);
break;
case NEXT_SIBLING:
adoptAsNextSibling(context, parent, thisNode, otherNode);
break;
case REPLACEMENT:
adoptAsReplacement(context, parent, thisNode, otherNode);
break;
}
} catch (Exception e) {
throw context.runtime.newRuntimeError(e.toString());
Expand Down
18 changes: 9 additions & 9 deletions ext/java/nokogiri/XmlXpathContext.java
Expand Up @@ -203,15 +203,15 @@ public class XmlXpathContext extends RubyObject
}

switch (xobj.getType()) {
case XObject.CLASS_BOOLEAN :
return context.runtime.newBoolean(xobj.bool());
case XObject.CLASS_NUMBER :
return context.runtime.newFloat(xobj.num());
case XObject.CLASS_NODESET :
IRubyObject[] nodes = nodeListToRubyArray(context.runtime, xobj.nodelist());
return XmlNodeSet.newNodeSet(context.runtime, nodes, this.context);
default :
return context.runtime.newString(xobj.str());
case XObject.CLASS_BOOLEAN :
return context.runtime.newBoolean(xobj.bool());
case XObject.CLASS_NUMBER :
return context.runtime.newFloat(xobj.num());
case XObject.CLASS_NODESET :
IRubyObject[] nodes = nodeListToRubyArray(context.runtime, xobj.nodelist());
return XmlNodeSet.newNodeSet(context.runtime, nodes, this.context);
default :
return context.runtime.newString(xobj.str());
}
}

Expand Down
12 changes: 6 additions & 6 deletions ext/java/nokogiri/XsltStylesheet.java
Expand Up @@ -213,12 +213,12 @@ public class XsltStylesheet extends RubyObject
}

switch (elistener.getErrorType()) {
case ERROR:
case FATAL:
throw runtime.newRuntimeError(elistener.getErrorMessage());
case WARNING:
default:
// no-op
case ERROR:
case FATAL:
throw runtime.newRuntimeError(elistener.getErrorMessage());
case WARNING:
default:
// no-op
}

if (stringResult == null) {
Expand Down
106 changes: 53 additions & 53 deletions ext/java/nokogiri/internals/NokogiriHelpers.java
Expand Up @@ -116,59 +116,59 @@ public class NokogiriHelpers
if (node == null) { return runtime.getNil(); }
// this is slow; need a way to cache nokogiri classes/modules somewhere
switch (node.getNodeType()) {
case Node.ELEMENT_NODE:
XmlElement xmlElement = (XmlElement) NokogiriService.XML_ELEMENT_ALLOCATOR.allocate(runtime, getNokogiriClass(runtime,
"Nokogiri::XML::Element"));
xmlElement.setNode(runtime, node);
return xmlElement;
case Node.ATTRIBUTE_NODE:
XmlAttr xmlAttr = (XmlAttr) NokogiriService.XML_ATTR_ALLOCATOR.allocate(runtime, getNokogiriClass(runtime,
"Nokogiri::XML::Attr"));
xmlAttr.setNode(runtime, node);
return xmlAttr;
case Node.TEXT_NODE:
XmlText xmlText = (XmlText) NokogiriService.XML_TEXT_ALLOCATOR.allocate(runtime, getNokogiriClass(runtime,
"Nokogiri::XML::Text"));
xmlText.setNode(runtime, node);
return xmlText;
case Node.COMMENT_NODE:
XmlComment xmlComment = (XmlComment) NokogiriService.XML_COMMENT_ALLOCATOR.allocate(runtime, getNokogiriClass(runtime,
"Nokogiri::XML::Comment"));
xmlComment.setNode(runtime, node);
return xmlComment;
case Node.ENTITY_NODE:
return new XmlNode(runtime, getNokogiriClass(runtime, "Nokogiri::XML::EntityDecl"), node);
case Node.ENTITY_REFERENCE_NODE:
XmlEntityReference xmlEntityRef = (XmlEntityReference) NokogiriService.XML_ENTITY_REFERENCE_ALLOCATOR.allocate(runtime,
getNokogiriClass(runtime, "Nokogiri::XML::EntityReference"));
xmlEntityRef.setNode(runtime, node);
return xmlEntityRef;
case Node.PROCESSING_INSTRUCTION_NODE:
XmlProcessingInstruction xmlProcessingInstruction = (XmlProcessingInstruction)
NokogiriService.XML_PROCESSING_INSTRUCTION_ALLOCATOR.allocate(runtime, getNokogiriClass(runtime,
"Nokogiri::XML::ProcessingInstruction"));
xmlProcessingInstruction.setNode(runtime, node);
return xmlProcessingInstruction;
case Node.CDATA_SECTION_NODE:
XmlCdata xmlCdata = (XmlCdata) NokogiriService.XML_CDATA_ALLOCATOR.allocate(runtime, getNokogiriClass(runtime,
"Nokogiri::XML::CDATA"));
xmlCdata.setNode(runtime, node);
return xmlCdata;
case Node.DOCUMENT_NODE:
XmlDocument xmlDocument = (XmlDocument) NokogiriService.XML_DOCUMENT_ALLOCATOR.allocate(runtime,
getNokogiriClass(runtime, "Nokogiri::XML::Document"));
xmlDocument.setDocumentNode(runtime, (Document) node);
return xmlDocument;
case Node.DOCUMENT_TYPE_NODE:
XmlDtd xmlDtd = (XmlDtd) NokogiriService.XML_DTD_ALLOCATOR.allocate(runtime, getNokogiriClass(runtime,
"Nokogiri::XML::DTD"));
xmlDtd.setNode(runtime, node);
return xmlDtd;
default:
XmlNode xmlNode = (XmlNode) NokogiriService.XML_NODE_ALLOCATOR.allocate(runtime, getNokogiriClass(runtime,
"Nokogiri::XML::Node"));
xmlNode.setNode(runtime, node);
return xmlNode;
case Node.ELEMENT_NODE:
XmlElement xmlElement = (XmlElement) NokogiriService.XML_ELEMENT_ALLOCATOR.allocate(runtime, getNokogiriClass(runtime,
"Nokogiri::XML::Element"));
xmlElement.setNode(runtime, node);
return xmlElement;
case Node.ATTRIBUTE_NODE:
XmlAttr xmlAttr = (XmlAttr) NokogiriService.XML_ATTR_ALLOCATOR.allocate(runtime, getNokogiriClass(runtime,
"Nokogiri::XML::Attr"));
xmlAttr.setNode(runtime, node);
return xmlAttr;
case Node.TEXT_NODE:
XmlText xmlText = (XmlText) NokogiriService.XML_TEXT_ALLOCATOR.allocate(runtime, getNokogiriClass(runtime,
"Nokogiri::XML::Text"));
xmlText.setNode(runtime, node);
return xmlText;
case Node.COMMENT_NODE:
XmlComment xmlComment = (XmlComment) NokogiriService.XML_COMMENT_ALLOCATOR.allocate(runtime, getNokogiriClass(runtime,
"Nokogiri::XML::Comment"));
xmlComment.setNode(runtime, node);
return xmlComment;
case Node.ENTITY_NODE:
return new XmlNode(runtime, getNokogiriClass(runtime, "Nokogiri::XML::EntityDecl"), node);
case Node.ENTITY_REFERENCE_NODE:
XmlEntityReference xmlEntityRef = (XmlEntityReference) NokogiriService.XML_ENTITY_REFERENCE_ALLOCATOR.allocate(runtime,
getNokogiriClass(runtime, "Nokogiri::XML::EntityReference"));
xmlEntityRef.setNode(runtime, node);
return xmlEntityRef;
case Node.PROCESSING_INSTRUCTION_NODE:
XmlProcessingInstruction xmlProcessingInstruction = (XmlProcessingInstruction)
NokogiriService.XML_PROCESSING_INSTRUCTION_ALLOCATOR.allocate(runtime, getNokogiriClass(runtime,
"Nokogiri::XML::ProcessingInstruction"));
xmlProcessingInstruction.setNode(runtime, node);
return xmlProcessingInstruction;
case Node.CDATA_SECTION_NODE:
XmlCdata xmlCdata = (XmlCdata) NokogiriService.XML_CDATA_ALLOCATOR.allocate(runtime, getNokogiriClass(runtime,
"Nokogiri::XML::CDATA"));
xmlCdata.setNode(runtime, node);
return xmlCdata;
case Node.DOCUMENT_NODE:
XmlDocument xmlDocument = (XmlDocument) NokogiriService.XML_DOCUMENT_ALLOCATOR.allocate(runtime,
getNokogiriClass(runtime, "Nokogiri::XML::Document"));
xmlDocument.setDocumentNode(runtime, (Document) node);
return xmlDocument;
case Node.DOCUMENT_TYPE_NODE:
XmlDtd xmlDtd = (XmlDtd) NokogiriService.XML_DTD_ALLOCATOR.allocate(runtime, getNokogiriClass(runtime,
"Nokogiri::XML::DTD"));
xmlDtd.setNode(runtime, node);
return xmlDtd;
default:
XmlNode xmlNode = (XmlNode) NokogiriService.XML_NODE_ALLOCATOR.allocate(runtime, getNokogiriClass(runtime,
"Nokogiri::XML::Node"));
xmlNode.setNode(runtime, node);
return xmlNode;
}
}

Expand Down