nokogiri 1.6.2.rc2-java → 1.6.2.rc3-java
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of nokogiri might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/.travis.yml +2 -0
- data/CHANGELOG.ja.rdoc +9 -1
- data/CHANGELOG.rdoc +11 -1
- data/Rakefile +2 -1
- data/ext/java/nokogiri/XmlDocument.java +2 -2
- data/ext/java/nokogiri/XmlNode.java +62 -32
- data/ext/java/nokogiri/XmlXpathContext.java +36 -8
- data/ext/java/nokogiri/internals/NokogiriHelpers.java +23 -21
- data/ext/java/nokogiri/internals/NokogiriNamespaceCache.java +59 -54
- data/ext/nokogiri/extconf.rb +14 -0
- data/ext/nokogiri/xml_node.c +65 -3
- data/lib/nokogiri/css/xpath_visitor.rb +1 -1
- data/lib/nokogiri/nokogiri.jar +0 -0
- data/lib/nokogiri/version.rb +1 -1
- data/test/css/test_parser.rb +5 -5
- data/test/html/test_document_fragment.rb +6 -0
- data/test/namespaces/test_namespaces_aliased_default.rb +24 -0
- data/test/namespaces/test_namespaces_preservation.rb +31 -0
- data/test/xml/test_text.rb +15 -0
- data/test_all +3 -3
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0dfa0556a5cd5aa7896420b87b700daeb9f93e78
|
4
|
+
data.tar.gz: dd9a7086d2ee770791d40f7791417ad3d1d5d5d2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cd80730fb14c2140c9f9865c2c097ef8999f4a627fde6497c7ba694380256af7e81902900f989df185018a2fdda7af878254841ecea6bcf109ad9f97dff7f3a7
|
7
|
+
data.tar.gz: de6cc13b34efd97c9fd4be5bd4728d5e5225de7f1d4360d11fbda86c058f153f1f0543f25d9640dac1bd05fc11f3b117d903844df6d37e3b2fa68745e68ad891
|
data/.travis.yml
CHANGED
data/CHANGELOG.ja.rdoc
CHANGED
@@ -10,6 +10,7 @@
|
|
10
10
|
and add support for native builds on Windows. #864, #989, #1072
|
11
11
|
* (MRI) iconvが Windows-31J をサポートしていない場合は CP932 のエイリアスとして扱うようにした #836
|
12
12
|
* (MRI) 同梱ライブラリを静的にリンクするようになった (静的リンクをオフにするにはextconf.rbに --disable-static を渡す) #923
|
13
|
+
* (MRI) CRubyのバグ #9760 に起因するライブラリパス(LIBPATH)の優先順位問題に対応した
|
13
14
|
* (MRI) 同梱ライブラリのビルド後に不要になったディレクトリ群を自動的に削除するようになった (デバッグ等の目的で残すようにするにはextconf.rbに --disable-clean を渡す) #952
|
14
15
|
* (MRI) FreeBSDなど、libiconvがシステム標準ディレクトリ外にある環境でlibxml2がiconvサポート付きで正しくビルドされるようになった
|
15
16
|
* nthセレクタにおいてan-bを認識するようになった #886 (Magnus Bergmarkに感謝!)
|
@@ -27,13 +28,20 @@
|
|
27
28
|
* :only-child疑似クラスが:not疑似クラスの中にある場合に正常な動作が行われるようになった #858 (Yamagishi Kazutoshiに感謝!)
|
28
29
|
* 同梱のライブラリを使う場合にはextconf.rbでpkg_configを呼ばなくなった #931 (Shota Fukumoriに感謝!)
|
29
30
|
* Nokogiri.parse()がRSS文書などをHTML文書として誤認する問題を修正 #932 (Yamagishi Kazutoshiに感謝!)
|
31
|
+
* (MRI) ノードに対して子ノードを追加する際、ノードタイプをチェックするようにした。従来はテキストノードに別のテキストノードを追加する操作によりSEGVが発生していた。 #1092
|
30
32
|
* (JRuby) XSD validation crashes in Java version. #373
|
31
33
|
* (JRuby) Document already has a root node error while using Builder. #646
|
32
34
|
* (JRuby) c14n tests are all passing on JRuby. #226
|
33
35
|
* Parsing empty documents raise SyntaxError in strict mode. #1005
|
34
36
|
* (JRuby) Make xpath faster by caching the xpath context. #741
|
35
37
|
* (JRuby) XML SAX push parser leaks memory on JRuby, but not on MRI. #998
|
36
|
-
|
38
|
+
* (JRUby) JRubyによるディフォルトネームスペースエイリアスの振る舞いがCRubyと同じではない。#940
|
39
|
+
* (JRuby) JRubyによるネームスペースのパースと追加の振る舞いが一致していない。 #943
|
40
|
+
* (JRuby) Builderで作ったドキュメントとクローンしたドキュメントではXpathの結果が違う。#1034
|
41
|
+
* (JRuby) Javaの実装はネームスペースを忘れることがある。 #902
|
42
|
+
* (JRuby) JRuby-Nokogiriはネームスペーススコープ内のアトリビュートを正しく認識しない。#1081
|
43
|
+
* (JRuby) JRuby-Nokogiriはコメントノードの名前が違う。#1080
|
44
|
+
* (JRuby) JAXPExtensionsProvider / Java 7 / Secure Processingに問題がある。 #1070
|
37
45
|
|
38
46
|
=== 1.6.1 / 2013年12月14日
|
39
47
|
|
data/CHANGELOG.rdoc
CHANGED
@@ -11,6 +11,8 @@
|
|
11
11
|
* (MRI) Alias CP932 to Windows-31J if iconv does not support Windows-31J.
|
12
12
|
* (MRI) Nokogiri now links packaged libraries statically. To
|
13
13
|
disable static linking, pass --disable-static to extconf.rb. #923
|
14
|
+
* (MRI) Fix a library path (LIBPATH) precedence problem caused by CRuby
|
15
|
+
bug #9760.
|
14
16
|
* (MRI) Nokogiri automatically deletes directories of packaged
|
15
17
|
libraries only used during build. To keep them for debugging
|
16
18
|
purposes, pass --disable-clean to extconf.rb. #952
|
@@ -41,13 +43,21 @@
|
|
41
43
|
#931 (Thanks, Shota Fukumori!)
|
42
44
|
* Nokogiri.parse() does not mistake a non-HTML document like a RSS
|
43
45
|
document as HTML document. #932 (Thanks, Yamagishi Kazutoshi!)
|
46
|
+
* (MRI) Perform a node type check before adding a child node to another. Previously adding a text node to another as a child could cause a SEGV. #1092
|
44
47
|
* (JRuby) XSD validation crashes in Java version. #373
|
45
48
|
* (JRuby) Document already has a root node error while using Builder. #646
|
46
49
|
* (JRuby) c14n tests are all passing on JRuby. #226
|
47
50
|
* Parsing empty documents raise SyntaxError in strict mode. #1005
|
48
51
|
* (JRuby) Make xpath faster by caching the xpath context. #741
|
49
52
|
* (JRuby) XML SAX push parser leaks memory on JRuby, but not on MRI. #998
|
50
|
-
|
53
|
+
* (JRUby) Inconsistent behavior aliasing the default namespace. #940
|
54
|
+
* (JRuby) Inconsistent behavior between parsing and adding namespaces. #943
|
55
|
+
* (JRuby) Xpath returns inconsistent result set on cloned document with
|
56
|
+
namespaces and attributes. #1034
|
57
|
+
* (JRuby) Java-Implementation forgets element namespaces #902
|
58
|
+
* (JRuby) JRuby-Nokogiri does not recognise attributes inside namespaces #1081
|
59
|
+
* (JRuby) JRuby-Nokogiri has different comment node name #1080
|
60
|
+
* (JRuby) JAXPExtensionsProvider / Java 7 / Secure Processing #1070
|
51
61
|
|
52
62
|
=== 1.6.1 / 2013-12-14
|
53
63
|
|
data/Rakefile
CHANGED
@@ -110,6 +110,8 @@ HOE = Hoe.spec 'nokogiri' do
|
|
110
110
|
developer 'Tim Elliott', 'tle@holymonkey.com'
|
111
111
|
developer 'Akinori MUSHA', 'knu@idaemons.org'
|
112
112
|
|
113
|
+
license "MIT"
|
114
|
+
|
113
115
|
self.readme_file = ['README', ENV['HLANG'], 'rdoc'].compact.join('.')
|
114
116
|
self.history_file = ['CHANGELOG', ENV['HLANG'], 'rdoc'].compact.join('.')
|
115
117
|
|
@@ -157,7 +159,6 @@ HOE = Hoe.spec 'nokogiri' do
|
|
157
159
|
|
158
160
|
self.testlib = :minitest
|
159
161
|
end
|
160
|
-
HOE.spec.licenses = ['MIT']
|
161
162
|
|
162
163
|
# ----------------------------------------
|
163
164
|
|
@@ -1,7 +1,7 @@
|
|
1
1
|
/**
|
2
2
|
* (The MIT License)
|
3
3
|
*
|
4
|
-
* Copyright (c) 2008 -
|
4
|
+
* Copyright (c) 2008 - 2014:
|
5
5
|
*
|
6
6
|
* * {Aaron Patterson}[http://tenderlovemaking.com]
|
7
7
|
* * {Mike Dalessio}[http://mike.daless.io]
|
@@ -186,7 +186,7 @@ public class XmlDocument extends XmlNode {
|
|
186
186
|
if (nodePrefix == null) { // default namespace
|
187
187
|
NokogiriHelpers.renameNode(node, default_href, node.getNodeName());
|
188
188
|
} else {
|
189
|
-
XmlNamespace xmlNamespace = nsCache.get(nodePrefix);
|
189
|
+
XmlNamespace xmlNamespace = nsCache.get(node, nodePrefix);
|
190
190
|
String href = rubyStringToString(xmlNamespace.href(context));
|
191
191
|
NokogiriHelpers.renameNode(node, href, node.getNodeName());
|
192
192
|
}
|
@@ -1,7 +1,7 @@
|
|
1
1
|
/**
|
2
2
|
* (The MIT License)
|
3
3
|
*
|
4
|
-
* Copyright (c) 2008 -
|
4
|
+
* Copyright (c) 2008 - 2014:
|
5
5
|
*
|
6
6
|
* * {Aaron Patterson}[http://tenderlovemaking.com]
|
7
7
|
* * {Mike Dalessio}[http://mike.daless.io]
|
@@ -242,7 +242,7 @@ public class XmlNode extends RubyObject {
|
|
242
242
|
public Object clone() throws CloneNotSupportedException {
|
243
243
|
return super.clone();
|
244
244
|
}
|
245
|
-
|
245
|
+
|
246
246
|
protected void resetCache() {
|
247
247
|
node.setUserData(NokogiriHelpers.CACHED_NODE, this, null);
|
248
248
|
}
|
@@ -400,7 +400,7 @@ public class XmlNode extends RubyObject {
|
|
400
400
|
}
|
401
401
|
|
402
402
|
resultLines[i] = curInd.toString() + curLine;
|
403
|
-
|
403
|
+
|
404
404
|
if(!curLine.endsWith("/>") && !closingTag) {
|
405
405
|
curInd.append(indentString);
|
406
406
|
}
|
@@ -451,7 +451,6 @@ public class XmlNode extends RubyObject {
|
|
451
451
|
return value.length() == 0 ? null : value;
|
452
452
|
}
|
453
453
|
|
454
|
-
|
455
454
|
public void post_add_child(ThreadContext context, XmlNode current, XmlNode child) {
|
456
455
|
}
|
457
456
|
|
@@ -575,7 +574,9 @@ public class XmlNode extends RubyObject {
|
|
575
574
|
str = NokogiriHelpers.getLocalPart(str);
|
576
575
|
}
|
577
576
|
if (str == null) str = "";
|
577
|
+
if (str.startsWith("#")) str = str.substring(1); // eliminates '#'
|
578
578
|
name = NokogiriHelpers.stringOrBlank(context.getRuntime(), str);
|
579
|
+
|
579
580
|
return name;
|
580
581
|
}
|
581
582
|
|
@@ -588,23 +589,29 @@ public class XmlNode extends RubyObject {
|
|
588
589
|
public IRubyObject add_namespace_definition(ThreadContext context,
|
589
590
|
IRubyObject prefix,
|
590
591
|
IRubyObject href) {
|
592
|
+
String prefixString = rubyStringToString(prefix);
|
593
|
+
String hrefString = rubyStringToString(href);
|
594
|
+
|
595
|
+
NokogiriNamespaceCache nsCache = NokogiriHelpers.getNamespaceCacheFormNode(node);
|
596
|
+
XmlNamespace cachedNamespace = nsCache.get(prefixString, hrefString);
|
597
|
+
if (cachedNamespace != null) return cachedNamespace;
|
598
|
+
|
591
599
|
Node namespaceOwner;
|
592
600
|
if (node.getNodeType() == Node.ELEMENT_NODE) {
|
593
601
|
namespaceOwner = node;
|
594
602
|
Element element = (Element) node;
|
595
|
-
|
603
|
+
// adds namespace as node's attribute
|
596
604
|
final String uri = "http://www.w3.org/2000/xmlns/";
|
597
605
|
String qName =
|
598
|
-
prefix.isNil() ? "xmlns" : "xmlns:" +
|
599
|
-
element.setAttributeNS(uri, qName,
|
606
|
+
prefix.isNil() ? "xmlns" : "xmlns:" + prefixString;
|
607
|
+
element.setAttributeNS(uri, qName, hrefString);
|
600
608
|
}
|
601
609
|
else if (node.getNodeType() == Node.ATTRIBUTE_NODE) namespaceOwner = ((Attr)node).getOwnerElement();
|
602
610
|
else namespaceOwner = node.getParentNode();
|
603
611
|
XmlNamespace ns = XmlNamespace.createFromPrefixAndHref(namespaceOwner, prefix, href);
|
604
612
|
if (node != namespaceOwner) {
|
605
|
-
this.node = NokogiriHelpers.renameNode(node, ns.getHref(), ns.getPrefix() + node.getLocalName());
|
613
|
+
this.node = NokogiriHelpers.renameNode(node, ns.getHref(), ns.getPrefix() + ":" + node.getLocalName());
|
606
614
|
}
|
607
|
-
|
608
615
|
updateNodeNamespaceIfNecessary(context, ns);
|
609
616
|
|
610
617
|
return ns;
|
@@ -676,7 +683,7 @@ public class XmlNode extends RubyObject {
|
|
676
683
|
xmlNodeSet.setNodeList(node.getChildNodes());
|
677
684
|
return xmlNodeSet;
|
678
685
|
}
|
679
|
-
|
686
|
+
|
680
687
|
@JRubyMethod
|
681
688
|
public IRubyObject first_element_child(ThreadContext context) {
|
682
689
|
List<Node> elementNodes = new ArrayList<Node>();
|
@@ -692,7 +699,7 @@ public class XmlNode extends RubyObject {
|
|
692
699
|
if (elementNodes.size() == 0) return context.getRuntime().getNil();
|
693
700
|
return getCachedNodeOrCreate(context.getRuntime(), elementNodes.get(elementNodes.size()-1));
|
694
701
|
}
|
695
|
-
|
702
|
+
|
696
703
|
@JRubyMethod(name = {"element_children", "elements"})
|
697
704
|
public IRubyObject element_children(ThreadContext context) {
|
698
705
|
List<Node> elementNodes = new ArrayList<Node>();
|
@@ -702,7 +709,7 @@ public class XmlNode extends RubyObject {
|
|
702
709
|
XmlNodeSet xmlNodeSet = XmlNodeSet.newXmlNodeSet(context, array);
|
703
710
|
return xmlNodeSet;
|
704
711
|
}
|
705
|
-
|
712
|
+
|
706
713
|
private void addElements(Node n, List<Node> nodes, boolean isFirstOnly) {
|
707
714
|
NodeList children = n.getChildNodes();
|
708
715
|
if (children.getLength() == 0) return;
|
@@ -764,7 +771,7 @@ public class XmlNode extends RubyObject {
|
|
764
771
|
XmlDomParserContext ctx;
|
765
772
|
InputStream istream;
|
766
773
|
XmlDocument document;
|
767
|
-
|
774
|
+
|
768
775
|
IRubyObject d = document(context);
|
769
776
|
Ruby runtime = context.getRuntime();
|
770
777
|
if (d != null && d instanceof XmlDocument) {
|
@@ -772,7 +779,7 @@ public class XmlNode extends RubyObject {
|
|
772
779
|
} else {
|
773
780
|
return runtime.getNil();
|
774
781
|
}
|
775
|
-
|
782
|
+
|
776
783
|
if (document instanceof HtmlDocument) {
|
777
784
|
klass = getNokogiriClass(runtime, "Nokogiri::HTML::Document");
|
778
785
|
ctx = new HtmlDomParserContext(runtime, options);
|
@@ -789,7 +796,7 @@ public class XmlNode extends RubyObject {
|
|
789
796
|
|
790
797
|
ctx.setInputSource(istream);
|
791
798
|
XmlDocument doc = ctx.parse(context, klass, runtime.getNil());
|
792
|
-
|
799
|
+
|
793
800
|
RubyArray documentErrors = getErrorArray(document);
|
794
801
|
RubyArray docErrors = getErrorArray(doc);
|
795
802
|
if (isErrorIncreased(documentErrors, docErrors)) {
|
@@ -800,7 +807,7 @@ public class XmlNode extends RubyObject {
|
|
800
807
|
XmlNodeSet xmlNodeSet = XmlNodeSet.newXmlNodeSet(context, RubyArray.newArray(runtime));
|
801
808
|
return xmlNodeSet;
|
802
809
|
}
|
803
|
-
|
810
|
+
|
804
811
|
// The first child might be document type node (dtd declaration).
|
805
812
|
// XmlNodeSet to be return should not have dtd decl in its list.
|
806
813
|
Node first;
|
@@ -815,7 +822,7 @@ public class XmlNode extends RubyObject {
|
|
815
822
|
XmlNodeSet xmlNodeSet = XmlNodeSet.newXmlNodeSet(context, nodeArray);
|
816
823
|
return xmlNodeSet;
|
817
824
|
}
|
818
|
-
|
825
|
+
|
819
826
|
private RubyArray getErrorArray(XmlDocument document) {
|
820
827
|
IRubyObject obj = document.getInstanceVariable("@errors");
|
821
828
|
if (obj != null && obj instanceof RubyArray) {
|
@@ -1046,8 +1053,7 @@ public class XmlNode extends RubyObject {
|
|
1046
1053
|
@JRubyMethod
|
1047
1054
|
public IRubyObject namespace(ThreadContext context) {
|
1048
1055
|
if (doc instanceof HtmlDocument) return context.getRuntime().getNil();
|
1049
|
-
|
1050
|
-
NokogiriNamespaceCache nsCache = xmlDocument.getNamespaceCache();
|
1056
|
+
NokogiriNamespaceCache nsCache = NokogiriHelpers.getNamespaceCacheFormNode(node);
|
1051
1057
|
String prefix = node.getPrefix();
|
1052
1058
|
XmlNamespace namespace = nsCache.get(prefix == null ? "" : prefix, node.getNamespaceURI());
|
1053
1059
|
if (namespace == null || namespace.isEmpty()) {
|
@@ -1085,18 +1091,42 @@ public class XmlNode extends RubyObject {
|
|
1085
1091
|
*/
|
1086
1092
|
@JRubyMethod
|
1087
1093
|
public IRubyObject namespace_scopes(ThreadContext context) {
|
1088
|
-
RubyArray
|
1089
|
-
|
1094
|
+
RubyArray scoped_namespaces = context.getRuntime().newArray();
|
1095
|
+
if (doc == null) return scoped_namespaces;
|
1096
|
+
if (doc instanceof HtmlDocument) return scoped_namespaces;
|
1090
1097
|
|
1091
|
-
|
1092
|
-
if (
|
1093
|
-
|
1094
|
-
|
1098
|
+
Node previousNode;
|
1099
|
+
if (node.getNodeType() == Node.ELEMENT_NODE) {
|
1100
|
+
previousNode = node;
|
1101
|
+
} else if (node.getNodeType() == Node.ATTRIBUTE_NODE) {
|
1102
|
+
previousNode = ((Attr)node).getOwnerElement();
|
1095
1103
|
} else {
|
1096
|
-
|
1104
|
+
previousNode = findPreviousElement(node);
|
1105
|
+
}
|
1106
|
+
if (previousNode == null) return scoped_namespaces;
|
1107
|
+
|
1108
|
+
List<String> prefixes_in_scope = new ArrayList<String>();
|
1109
|
+
NokogiriNamespaceCache nsCache = NokogiriHelpers.getNamespaceCacheFormNode(previousNode);
|
1110
|
+
for (Node previous=previousNode; previous != null; ) {
|
1111
|
+
List<XmlNamespace> namespaces = nsCache.get(previous);
|
1112
|
+
for (XmlNamespace namespace : namespaces) {
|
1113
|
+
if (prefixes_in_scope.contains(namespace.getPrefix())) continue;
|
1114
|
+
scoped_namespaces.append(namespace);
|
1115
|
+
prefixes_in_scope.add(namespace.getPrefix());
|
1116
|
+
}
|
1117
|
+
previous = findPreviousElement(previous);
|
1097
1118
|
}
|
1119
|
+
return scoped_namespaces;
|
1120
|
+
}
|
1098
1121
|
|
1099
|
-
|
1122
|
+
private Node findPreviousElement(Node n) {
|
1123
|
+
Node previous = n.getPreviousSibling() == null ? n.getParentNode() : n.getPreviousSibling();
|
1124
|
+
if (previous == null || previous.getNodeType() == Node.DOCUMENT_NODE) return null;
|
1125
|
+
if (previous.getNodeType() == Node.ELEMENT_NODE) {
|
1126
|
+
return previous;
|
1127
|
+
} else {
|
1128
|
+
return findPreviousElement(previous);
|
1129
|
+
}
|
1100
1130
|
}
|
1101
1131
|
|
1102
1132
|
@JRubyMethod(name="namespaced_key?")
|
@@ -1161,11 +1191,11 @@ public class XmlNode extends RubyObject {
|
|
1161
1191
|
|
1162
1192
|
return io;
|
1163
1193
|
}
|
1164
|
-
|
1194
|
+
|
1165
1195
|
private boolean isHtmlDoc(ThreadContext context) {
|
1166
1196
|
return document(context).getMetaClass().isKindOfModule(getNokogiriClass(context.getRuntime(), "Nokogiri::HTML::Document"));
|
1167
1197
|
}
|
1168
|
-
|
1198
|
+
|
1169
1199
|
private boolean isFragment() {
|
1170
1200
|
if (node instanceof DocumentFragment) return true;
|
1171
1201
|
if (node.getParentNode() != null && node.getParentNode() instanceof DocumentFragment) return true;
|
@@ -1575,7 +1605,7 @@ public class XmlNode extends RubyObject {
|
|
1575
1605
|
if (nextSib != null &&
|
1576
1606
|
nextSib.getNodeType() == Node.TEXT_NODE &&
|
1577
1607
|
otherNode.getNodeType() == Node.TEXT_NODE) return;
|
1578
|
-
|
1608
|
+
|
1579
1609
|
if (nextSib != null) {
|
1580
1610
|
parent.insertBefore(otherNode, nextSib);
|
1581
1611
|
} else {
|
@@ -1601,7 +1631,7 @@ public class XmlNode extends RubyObject {
|
|
1601
1631
|
throw context.getRuntime().newRuntimeError(prefix + e.toString());
|
1602
1632
|
}
|
1603
1633
|
}
|
1604
|
-
|
1634
|
+
|
1605
1635
|
/**
|
1606
1636
|
* Add <code>other</code> as a child of <code>this</code>.
|
1607
1637
|
*/
|
@@ -1633,7 +1663,7 @@ public class XmlNode extends RubyObject {
|
|
1633
1663
|
public IRubyObject add_next_sibling_node(ThreadContext context, IRubyObject other) {
|
1634
1664
|
return adoptAs(context, AdoptScheme.NEXT_SIBLING, other);
|
1635
1665
|
}
|
1636
|
-
|
1666
|
+
|
1637
1667
|
/**
|
1638
1668
|
* call-seq:
|
1639
1669
|
* process_xincludes(options)
|
@@ -1,7 +1,7 @@
|
|
1
1
|
/**
|
2
2
|
* (The MIT License)
|
3
3
|
*
|
4
|
-
* Copyright (c) 2008 -
|
4
|
+
* Copyright (c) 2008 - 2014:
|
5
5
|
*
|
6
6
|
* * {Aaron Patterson}[http://tenderlovemaking.com]
|
7
7
|
* * {Mike Dalessio}[http://mike.daless.io]
|
@@ -34,6 +34,8 @@ package nokogiri;
|
|
34
34
|
|
35
35
|
import static nokogiri.internals.NokogiriHelpers.getNokogiriClass;
|
36
36
|
|
37
|
+
import java.lang.reflect.Constructor;
|
38
|
+
import java.lang.reflect.InvocationTargetException;
|
37
39
|
import java.util.Set;
|
38
40
|
|
39
41
|
import javax.xml.transform.TransformerException;
|
@@ -88,18 +90,18 @@ public class XmlXpathContext extends RubyObject {
|
|
88
90
|
variableResolver = NokogiriXPathVariableResolver.create();
|
89
91
|
}
|
90
92
|
|
91
|
-
|
93
|
+
private void setNode(XmlNode node) throws IllegalArgumentException, ClassNotFoundException, InstantiationException, IllegalAccessException, InvocationTargetException {
|
92
94
|
Node doc = node.getNode().getOwnerDocument();
|
93
95
|
if (doc == null) {
|
94
|
-
|
96
|
+
doc = node.getNode();
|
95
97
|
}
|
96
98
|
xpathSupport = (XPathContext) doc.getUserData(XPATH_CONTEXT);
|
97
99
|
|
98
100
|
if (xpathSupport == null) {
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
101
|
+
JAXPExtensionsProvider jep = getProviderInstance();
|
102
|
+
xpathSupport = new XPathContext(jep);
|
103
|
+
xpathSupport.setVarStack(new JAXPVariableStack(variableResolver));
|
104
|
+
doc.setUserData(XPATH_CONTEXT, xpathSupport, null);
|
103
105
|
}
|
104
106
|
|
105
107
|
context = node;
|
@@ -107,6 +109,20 @@ public class XmlXpathContext extends RubyObject {
|
|
107
109
|
prefixResolver = new JAXPPrefixResolver(nsContext);
|
108
110
|
}
|
109
111
|
|
112
|
+
private JAXPExtensionsProvider getProviderInstance() throws ClassNotFoundException, IllegalArgumentException, InstantiationException, IllegalAccessException, InvocationTargetException {
|
113
|
+
Class<?> clazz = Class.forName("com.sun.org.apache.xpath.internal.jaxp.JAXPExtensionsProvider");
|
114
|
+
Constructor[] constructors = clazz.getDeclaredConstructors();
|
115
|
+
for (int i = 0; i < constructors.length; i++) {
|
116
|
+
Class[] parameterTypes = constructors[i].getParameterTypes();
|
117
|
+
if (parameterTypes.length == 2) {
|
118
|
+
return (JAXPExtensionsProvider) constructors[i].newInstance(functionResolver, false);
|
119
|
+
} else if (parameterTypes.length == 1) {
|
120
|
+
return (JAXPExtensionsProvider) constructors[i].newInstance(functionResolver);
|
121
|
+
}
|
122
|
+
}
|
123
|
+
return null;
|
124
|
+
}
|
125
|
+
|
110
126
|
/**
|
111
127
|
* Create and return a copy of this object.
|
112
128
|
*
|
@@ -122,7 +138,19 @@ public class XmlXpathContext extends RubyObject {
|
|
122
138
|
XmlNode xmlNode = (XmlNode)node;
|
123
139
|
XmlXpathContext xmlXpathContext = (XmlXpathContext) NokogiriService.XML_XPATHCONTEXT_ALLOCATOR.allocate(thread_context.getRuntime(), (RubyClass)klazz);
|
124
140
|
XPathFactory.newInstance().newXPath();
|
125
|
-
|
141
|
+
try {
|
142
|
+
xmlXpathContext.setNode(xmlNode);
|
143
|
+
} catch (IllegalArgumentException e) {
|
144
|
+
throw thread_context.getRuntime().newRuntimeError(e.getMessage());
|
145
|
+
} catch (ClassNotFoundException e) {
|
146
|
+
throw thread_context.getRuntime().newRuntimeError(e.getMessage());
|
147
|
+
} catch (InstantiationException e) {
|
148
|
+
throw thread_context.getRuntime().newRuntimeError(e.getMessage());
|
149
|
+
} catch (IllegalAccessException e) {
|
150
|
+
throw thread_context.getRuntime().newRuntimeError(e.getMessage());
|
151
|
+
} catch (InvocationTargetException e) {
|
152
|
+
throw thread_context.getRuntime().newRuntimeError(e.getMessage());
|
153
|
+
}
|
126
154
|
return xmlXpathContext;
|
127
155
|
}
|
128
156
|
|
@@ -1,7 +1,7 @@
|
|
1
1
|
/**
|
2
2
|
* (The MIT License)
|
3
3
|
*
|
4
|
-
* Copyright (c) 2008 -
|
4
|
+
* Copyright (c) 2008 - 2014:
|
5
5
|
*
|
6
6
|
* * {Aaron Patterson}[http://tenderlovemaking.com]
|
7
7
|
* * {Mike Dalessio}[http://mike.daless.io]
|
@@ -557,7 +557,7 @@ public class NokogiriHelpers {
|
|
557
557
|
private static Pattern decoded_pattern = Pattern.compile("&|>|<|\r");
|
558
558
|
private static String[] encoded = {"&", ">", "<", " "};
|
559
559
|
private static String[] decoded = {"&", ">", "<", "\r"};
|
560
|
-
|
560
|
+
|
561
561
|
private static String convert(Pattern ptn, String input, String[] oldChars, String[] newChars) {
|
562
562
|
Matcher matcher = ptn.matcher(input);
|
563
563
|
boolean result = matcher.find();
|
@@ -577,11 +577,11 @@ public class NokogiriHelpers {
|
|
577
577
|
matcher.appendTail(sb);
|
578
578
|
return sb.toString();
|
579
579
|
}
|
580
|
-
|
580
|
+
|
581
581
|
public static String encodeJavaString(String s) {
|
582
582
|
return convert(decoded_pattern, s, decoded, encoded);
|
583
583
|
}
|
584
|
-
|
584
|
+
|
585
585
|
public static String decodeJavaString(String s) {
|
586
586
|
return convert(encoded_pattern, s, encoded, decoded);
|
587
587
|
}
|
@@ -617,7 +617,7 @@ public class NokogiriHelpers {
|
|
617
617
|
public static boolean isXmlBase(String attrName) {
|
618
618
|
return "xml:base".equals(attrName) || "xlink:href".equals(attrName);
|
619
619
|
}
|
620
|
-
|
620
|
+
|
621
621
|
public static boolean isWhitespaceText(ThreadContext context, IRubyObject obj) {
|
622
622
|
if (obj == null || obj.isNil()) return false;
|
623
623
|
|
@@ -628,11 +628,11 @@ public class NokogiriHelpers {
|
|
628
628
|
String content = rubyStringToString(node.content(context));
|
629
629
|
return content.trim().length() == 0;
|
630
630
|
}
|
631
|
-
|
631
|
+
|
632
632
|
public static boolean isWhitespaceText(String s) {
|
633
633
|
return s.trim().length() == 0;
|
634
634
|
}
|
635
|
-
|
635
|
+
|
636
636
|
public static String canonicalizeWhitespce(String s) {
|
637
637
|
StringBuilder sb = new StringBuilder();
|
638
638
|
char[] chars = s.toCharArray();
|
@@ -663,14 +663,14 @@ public class NokogiriHelpers {
|
|
663
663
|
RubyArray array = RubyArray.newArray(ruby, nodes.getLength());
|
664
664
|
return nodeListToRubyArray(ruby, nodes, array);
|
665
665
|
}
|
666
|
-
|
666
|
+
|
667
667
|
public static RubyArray nodeListToRubyArray(Ruby ruby, NodeList nodes, RubyArray array) {
|
668
668
|
for(int i = 0; i < nodes.getLength(); i++) {
|
669
669
|
array.append(NokogiriHelpers.getCachedNodeOrCreate(ruby, nodes.item(i)));
|
670
670
|
}
|
671
671
|
return array;
|
672
672
|
}
|
673
|
-
|
673
|
+
|
674
674
|
public static RubyArray nodeArrayToRubyArray(Ruby ruby, Node[] nodes) {
|
675
675
|
RubyArray n = RubyArray.newArray(ruby, nodes.length);
|
676
676
|
for(int i = 0; i < nodes.length; i++) {
|
@@ -678,7 +678,7 @@ public class NokogiriHelpers {
|
|
678
678
|
}
|
679
679
|
return n;
|
680
680
|
}
|
681
|
-
|
681
|
+
|
682
682
|
public static RubyArray namedNodeMapToRubyArray(Ruby ruby, NamedNodeMap map) {
|
683
683
|
RubyArray n = RubyArray.newArray(ruby, map.getLength());
|
684
684
|
for(int i = 0; i < map.getLength(); i++) {
|
@@ -686,7 +686,7 @@ public class NokogiriHelpers {
|
|
686
686
|
}
|
687
687
|
return n;
|
688
688
|
}
|
689
|
-
|
689
|
+
|
690
690
|
public static String getValidEncoding(Ruby runtime, IRubyObject encoding) {
|
691
691
|
if (encoding.isNil()) {
|
692
692
|
return guessEncoding();
|
@@ -694,7 +694,7 @@ public class NokogiriHelpers {
|
|
694
694
|
return ignoreInvalidEncoding(runtime, encoding);
|
695
695
|
}
|
696
696
|
}
|
697
|
-
|
697
|
+
|
698
698
|
private static String guessEncoding() {
|
699
699
|
String name = null;
|
700
700
|
if (name == null) name = System.getProperty("file.encoding");
|
@@ -709,7 +709,7 @@ public class NokogiriHelpers {
|
|
709
709
|
if (charsetNames.contains(givenEncoding)) return givenEncoding;
|
710
710
|
else return guessEncoding();
|
711
711
|
}
|
712
|
-
|
712
|
+
|
713
713
|
public static String adjustSystemIdIfNecessary(String currentDir, String scriptFileName, String baseURI, String systemId) {
|
714
714
|
if (systemId == null) return systemId;
|
715
715
|
File file = new File(systemId);
|
@@ -720,7 +720,7 @@ public class NokogiriHelpers {
|
|
720
720
|
if (path != null) return path;
|
721
721
|
return resolveSystemId(scriptFileName, systemId);
|
722
722
|
}
|
723
|
-
|
723
|
+
|
724
724
|
private static String resolveSystemId(String baseName, String systemId) {
|
725
725
|
if (baseName == null || baseName.length() < 1) return null;
|
726
726
|
String parentName = null;
|
@@ -734,13 +734,13 @@ public class NokogiriHelpers {
|
|
734
734
|
if (dtdFile.exists()) return dtdFile.getPath();
|
735
735
|
return null;
|
736
736
|
}
|
737
|
-
|
737
|
+
|
738
738
|
public static boolean isUTF8(String encoding) {
|
739
739
|
if (encoding == null) return true; // no need to convert encoding
|
740
740
|
int ret = Charset.forName(encoding).compareTo(Charset.forName("UTF-8"));
|
741
741
|
return ret == 0;
|
742
742
|
}
|
743
|
-
|
743
|
+
|
744
744
|
public static byte[] convertEncoding(Charset output_charset, String input_string) throws CharacterCodingException {
|
745
745
|
CharsetEncoder encoder = output_charset.newEncoder();
|
746
746
|
CharBuffer charBuffer = CharBuffer.wrap(input_string);
|
@@ -761,7 +761,6 @@ public class NokogiriHelpers {
|
|
761
761
|
} else {
|
762
762
|
return NokogiriHelpers.nkf(runtime, ruby_encoding, thing);
|
763
763
|
}
|
764
|
-
|
765
764
|
}
|
766
765
|
|
767
766
|
// This method is used from HTML documents. HTML meta tag with encoding specification
|
@@ -813,7 +812,7 @@ public class NokogiriHelpers {
|
|
813
812
|
return thing;
|
814
813
|
}
|
815
814
|
}
|
816
|
-
|
815
|
+
|
817
816
|
private static Charset shift_jis = Charset.forName("Shift_JIS");
|
818
817
|
private static Charset jis = Charset.forName("ISO-2022-JP");
|
819
818
|
private static Charset euc_jp = Charset.forName("EUC-JP");
|
@@ -827,11 +826,14 @@ public class NokogiriHelpers {
|
|
827
826
|
return !shouldEncode(text);
|
828
827
|
}
|
829
828
|
|
829
|
+
public static NokogiriNamespaceCache getNamespaceCacheFormNode(Node n) {
|
830
|
+
XmlDocument xmlDoc = (XmlDocument)getCachedNode(n.getOwnerDocument());
|
831
|
+
return xmlDoc.getNamespaceCache();
|
832
|
+
}
|
833
|
+
|
830
834
|
public static Node renameNode(Node n, String namespaceURI, String qualifiedName) throws DOMException {
|
831
835
|
Document doc = n.getOwnerDocument();
|
832
|
-
|
833
|
-
NokogiriNamespaceCache nsCache = xmlDoc.getNamespaceCache();
|
834
|
-
int oldHash = n.hashCode();
|
836
|
+
NokogiriNamespaceCache nsCache = getNamespaceCacheFormNode(n);
|
835
837
|
Node result = doc.renameNode(n, namespaceURI, qualifiedName);
|
836
838
|
if (result != n) {
|
837
839
|
nsCache.replaceNode(n, result);
|
@@ -1,7 +1,7 @@
|
|
1
1
|
/**
|
2
2
|
* (The MIT License)
|
3
3
|
*
|
4
|
-
* Copyright (c) 2008 -
|
4
|
+
* Copyright (c) 2008 - 2014:
|
5
5
|
*
|
6
6
|
* * {Aaron Patterson}[http://tenderlovemaking.com]
|
7
7
|
* * {Mike Dalessio}[http://mike.daless.io]
|
@@ -53,52 +53,65 @@ import org.w3c.dom.Node;
|
|
53
53
|
*/
|
54
54
|
public class NokogiriNamespaceCache {
|
55
55
|
|
56
|
-
private List<
|
57
|
-
private Map<
|
56
|
+
private List<String[]> keys;
|
57
|
+
private Map<String[], CacheEntry> cache; // pair of the index of a given key and entry
|
58
58
|
private XmlNamespace defaultNamespace = null;
|
59
59
|
|
60
60
|
public NokogiriNamespaceCache() {
|
61
|
-
keys = new ArrayList<
|
62
|
-
cache = new LinkedHashMap<
|
61
|
+
keys = new ArrayList<String[]>(); // keys are [prefix, href]
|
62
|
+
cache = new LinkedHashMap<String[], CacheEntry>();
|
63
63
|
}
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
64
|
+
|
65
|
+
public XmlNamespace getDefault() {
|
66
|
+
return defaultNamespace;
|
67
|
+
}
|
68
|
+
|
69
|
+
private String[] getKey(String prefix, String href) {
|
70
|
+
for (String[] key : keys) {
|
71
|
+
if (key[0].equals(prefix) && key[1].equals(href)) return key;
|
72
|
+
}
|
73
|
+
return null;
|
69
74
|
}
|
70
75
|
|
71
76
|
public XmlNamespace get(String prefix, String href) {
|
72
77
|
// prefix should not be null.
|
73
78
|
// In case of a default namespace, an empty string should be given to prefix argument.
|
74
79
|
if (prefix == null || href == null) return null;
|
75
|
-
|
76
|
-
|
77
|
-
|
80
|
+
String[] key = getKey(prefix, href);
|
81
|
+
if (key != null) {
|
82
|
+
return cache.get(key).namespace;
|
83
|
+
}
|
78
84
|
return null;
|
79
85
|
}
|
80
|
-
|
81
|
-
public XmlNamespace
|
82
|
-
return defaultNamespace;
|
83
|
-
}
|
84
|
-
|
85
|
-
public XmlNamespace get(String prefix) {
|
86
|
+
|
87
|
+
public XmlNamespace get(Node node, String prefix) {
|
86
88
|
if (prefix == null) return defaultNamespace;
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
for (int i=0; i < keys.size(); i++) {
|
91
|
-
if ((keys.get(i) & mask) == hash) {
|
92
|
-
return cache.get(i).namespace;
|
89
|
+
for (String[] key : keys) {
|
90
|
+
if (key[0].equals(prefix) && cache.get(key) != null && cache.get(key).isOwner(node)) {
|
91
|
+
return cache.get(key).namespace;
|
93
92
|
}
|
94
93
|
}
|
95
94
|
return null;
|
96
95
|
}
|
97
|
-
|
96
|
+
|
97
|
+
public List<XmlNamespace> get(String prefix) {
|
98
|
+
List<XmlNamespace> namespaces = new ArrayList<XmlNamespace>();
|
99
|
+
if (prefix == null) {
|
100
|
+
namespaces.add(defaultNamespace);
|
101
|
+
return namespaces;
|
102
|
+
}
|
103
|
+
for (String[] key : keys) {
|
104
|
+
if (key[0].equals(prefix) && cache.get(key) != null) {
|
105
|
+
namespaces.add(cache.get(key).namespace);
|
106
|
+
}
|
107
|
+
}
|
108
|
+
return namespaces;
|
109
|
+
}
|
110
|
+
|
98
111
|
public List<XmlNamespace> get(Node node) {
|
99
112
|
List<XmlNamespace> namespaces = new ArrayList<XmlNamespace>();
|
100
|
-
for (
|
101
|
-
CacheEntry entry = cache.get(
|
113
|
+
for (String[] key : keys) {
|
114
|
+
CacheEntry entry = cache.get(key);
|
102
115
|
if (entry.isOwner(node)) {
|
103
116
|
namespaces.add(entry.namespace);
|
104
117
|
}
|
@@ -111,33 +124,25 @@ public class NokogiriNamespaceCache {
|
|
111
124
|
// In case of a default namespace, an empty string should be given to prefix argument.
|
112
125
|
String prefixString = namespace.getPrefix();
|
113
126
|
String hrefString = namespace.getHref();
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
index = keys.size() - 1;
|
121
|
-
CacheEntry entry = new CacheEntry(namespace, ownerNode);
|
122
|
-
cache.put(index, entry);
|
123
|
-
if ("".equals(prefixString)) defaultNamespace = namespace;
|
124
|
-
}
|
127
|
+
if (getKey(prefixString, hrefString) != null) return;
|
128
|
+
String[] key = {prefixString, hrefString};
|
129
|
+
keys.add(key);
|
130
|
+
CacheEntry entry = new CacheEntry(namespace, ownerNode);
|
131
|
+
cache.put(key, entry);
|
132
|
+
if ("".equals(prefixString)) defaultNamespace = namespace;
|
125
133
|
}
|
126
134
|
|
127
135
|
public void remove(String prefix, String href) {
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
cache.remove(index);
|
133
|
-
}
|
134
|
-
keys.remove(index);
|
136
|
+
String[] key = getKey(prefix, href);
|
137
|
+
if (key == null) return;
|
138
|
+
keys.remove(key);
|
139
|
+
cache.remove(key);
|
135
140
|
}
|
136
|
-
|
141
|
+
|
137
142
|
public void clear() {
|
138
143
|
// removes namespace declarations from node
|
139
|
-
for (
|
140
|
-
CacheEntry entry = cache.get(
|
144
|
+
for (String[] key : cache.keySet()) {
|
145
|
+
CacheEntry entry = cache.get(key);
|
141
146
|
NamedNodeMap attributes = entry.ownerNode.getAttributes();
|
142
147
|
for (int j=0; j<attributes.getLength(); j++) {
|
143
148
|
String name = ((Attr)attributes.item(j)).getName();
|
@@ -150,10 +155,10 @@ public class NokogiriNamespaceCache {
|
|
150
155
|
cache.clear();
|
151
156
|
defaultNamespace = null;
|
152
157
|
}
|
153
|
-
|
158
|
+
|
154
159
|
public void replaceNode(Node oldNode, Node newNode) {
|
155
|
-
for (
|
156
|
-
CacheEntry entry = cache.get(
|
160
|
+
for (String[] key : keys) {
|
161
|
+
CacheEntry entry = cache.get(key);
|
157
162
|
if (entry.isOwner(oldNode)) {
|
158
163
|
entry.replaceOwner(newNode);
|
159
164
|
}
|
@@ -163,14 +168,14 @@ public class NokogiriNamespaceCache {
|
|
163
168
|
private class CacheEntry {
|
164
169
|
private XmlNamespace namespace;
|
165
170
|
private Node ownerNode;
|
166
|
-
|
171
|
+
|
167
172
|
CacheEntry(XmlNamespace namespace, Node ownerNode) {
|
168
173
|
this.namespace = namespace;
|
169
174
|
this.ownerNode = ownerNode;
|
170
175
|
}
|
171
176
|
|
172
177
|
public Boolean isOwner(Node n) {
|
173
|
-
return
|
178
|
+
return ownerNode.isSameNode(n);
|
174
179
|
}
|
175
180
|
|
176
181
|
public void replaceOwner(Node newNode) {
|
data/ext/nokogiri/extconf.rb
CHANGED
@@ -51,6 +51,20 @@ ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..', '..'))
|
|
51
51
|
# https://bugs.ruby-lang.org/issues/8074
|
52
52
|
@libdir_basename = "lib" if RUBY_VERSION < '2.1.0'
|
53
53
|
|
54
|
+
# Workaround for Ruby bug #9760, will be fixed in Ruby 2.2
|
55
|
+
class Array
|
56
|
+
alias orig_or |
|
57
|
+
|
58
|
+
def | other
|
59
|
+
if self.equal?($DEFLIBPATH) && other.equal?($LIBPATH)
|
60
|
+
# Make sure library directories we set take precedence over $(libdir)
|
61
|
+
other.orig_or(self)
|
62
|
+
else
|
63
|
+
self.orig_or(other)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end if RUBY_VERSION < '2.2.0'
|
67
|
+
|
54
68
|
if arg_config('--clean')
|
55
69
|
require 'pathname'
|
56
70
|
require 'fileutils'
|
data/ext/nokogiri/xml_node.c
CHANGED
@@ -139,7 +139,7 @@ static xmlNodePtr xmlReplaceNodeWrapper(xmlNodePtr pivot, xmlNodePtr new_node)
|
|
139
139
|
static VALUE reparent_node_with(VALUE pivot_obj, VALUE reparentee_obj, pivot_reparentee_func prf)
|
140
140
|
{
|
141
141
|
VALUE reparented_obj ;
|
142
|
-
xmlNodePtr reparentee, pivot, reparented, next_text, new_next_text ;
|
142
|
+
xmlNodePtr reparentee, pivot, reparented, next_text, new_next_text, parent ;
|
143
143
|
|
144
144
|
if(!rb_obj_is_kind_of(reparentee_obj, cNokogiriXmlNode))
|
145
145
|
rb_raise(rb_eArgError, "node must be a Nokogiri::XML::Node");
|
@@ -149,9 +149,71 @@ static VALUE reparent_node_with(VALUE pivot_obj, VALUE reparentee_obj, pivot_rep
|
|
149
149
|
Data_Get_Struct(reparentee_obj, xmlNode, reparentee);
|
150
150
|
Data_Get_Struct(pivot_obj, xmlNode, pivot);
|
151
151
|
|
152
|
-
|
153
|
-
|
152
|
+
/*
|
153
|
+
* Check if nodes given are appropriate to have a parent-child
|
154
|
+
* relationship, based on the DOM specification.
|
155
|
+
*
|
156
|
+
* cf. http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/core.html#ID-1590626202
|
157
|
+
*/
|
158
|
+
if (prf == xmlAddChild) {
|
159
|
+
parent = pivot;
|
160
|
+
} else {
|
161
|
+
parent = pivot->parent;
|
162
|
+
}
|
163
|
+
|
164
|
+
if (parent) {
|
165
|
+
switch (parent->type) {
|
166
|
+
case XML_DOCUMENT_NODE:
|
167
|
+
case XML_HTML_DOCUMENT_NODE:
|
168
|
+
switch (reparentee->type) {
|
169
|
+
case XML_ELEMENT_NODE:
|
170
|
+
case XML_PI_NODE:
|
171
|
+
case XML_COMMENT_NODE:
|
172
|
+
case XML_DOCUMENT_TYPE_NODE:
|
173
|
+
/*
|
174
|
+
* The DOM specification says no to adding text-like nodes
|
175
|
+
* directly to a document, but we allow it for compatibility.
|
176
|
+
*/
|
177
|
+
case XML_TEXT_NODE:
|
178
|
+
case XML_CDATA_SECTION_NODE:
|
179
|
+
case XML_ENTITY_REF_NODE:
|
180
|
+
goto ok;
|
181
|
+
}
|
182
|
+
break;
|
183
|
+
case XML_DOCUMENT_FRAG_NODE:
|
184
|
+
case XML_ENTITY_REF_NODE:
|
185
|
+
case XML_ELEMENT_NODE:
|
186
|
+
switch (reparentee->type) {
|
187
|
+
case XML_ELEMENT_NODE:
|
188
|
+
case XML_PI_NODE:
|
189
|
+
case XML_COMMENT_NODE:
|
190
|
+
case XML_TEXT_NODE:
|
191
|
+
case XML_CDATA_SECTION_NODE:
|
192
|
+
case XML_ENTITY_REF_NODE:
|
193
|
+
goto ok;
|
194
|
+
}
|
195
|
+
break;
|
196
|
+
case XML_ATTRIBUTE_NODE:
|
197
|
+
switch (reparentee->type) {
|
198
|
+
case XML_TEXT_NODE:
|
199
|
+
case XML_ENTITY_REF_NODE:
|
200
|
+
goto ok;
|
201
|
+
}
|
202
|
+
break;
|
203
|
+
case XML_TEXT_NODE:
|
204
|
+
/*
|
205
|
+
* xmlAddChild() breaks the DOM specification in that it allows
|
206
|
+
* adding a text node to another, in which case text nodes are
|
207
|
+
* coalesced, but since our JRuby version does not support such
|
208
|
+
* operation, we should inhibit it.
|
209
|
+
*/
|
210
|
+
break;
|
211
|
+
}
|
212
|
+
|
213
|
+
rb_raise(rb_eArgError, "cannot reparent %s there", rb_obj_classname(reparentee_obj));
|
214
|
+
}
|
154
215
|
|
216
|
+
ok:
|
155
217
|
xmlUnlinkNode(reparentee);
|
156
218
|
|
157
219
|
if (reparentee->doc != pivot->doc || reparentee->type == XML_TEXT_NODE) {
|
@@ -36,7 +36,7 @@ module Nokogiri
|
|
36
36
|
if node.value[1].is_a?(Nokogiri::CSS::Node) and node.value[1].type == :NTH
|
37
37
|
nth(node.value[1], :last => true, :child => true)
|
38
38
|
else
|
39
|
-
"count(following-
|
39
|
+
"count(following-sibling::*) = #{node.value[1].to_i-1}"
|
40
40
|
end
|
41
41
|
when /^(first|first-of-type)\(/
|
42
42
|
"position() = 1"
|
data/lib/nokogiri/nokogiri.jar
CHANGED
Binary file
|
data/lib/nokogiri/version.rb
CHANGED
data/test/css/test_parser.rb
CHANGED
@@ -174,11 +174,11 @@ module Nokogiri
|
|
174
174
|
end
|
175
175
|
|
176
176
|
def test_nth_child_selectors
|
177
|
-
assert_xpath '//a[count(preceding-sibling::*) = 0]',
|
178
|
-
assert_xpath '//a[count(preceding-sibling::*) = 98]',
|
179
|
-
assert_xpath '//a[count(following-sibling::*) = 0]',
|
180
|
-
assert_xpath '//a[count(following-
|
181
|
-
assert_xpath '//a[count(following-
|
177
|
+
assert_xpath '//a[count(preceding-sibling::*) = 0]', @parser.parse('a:first-child')
|
178
|
+
assert_xpath '//a[count(preceding-sibling::*) = 98]', @parser.parse('a:nth-child(99)')
|
179
|
+
assert_xpath '//a[count(following-sibling::*) = 0]', @parser.parse('a:last-child')
|
180
|
+
assert_xpath '//a[count(following-sibling::*) = 0]', @parser.parse('a:nth-last-child(1)')
|
181
|
+
assert_xpath '//a[count(following-sibling::*) = 98]', @parser.parse('a:nth-last-child(99)')
|
182
182
|
end
|
183
183
|
|
184
184
|
def test_miscellaneous_selectors
|
@@ -164,6 +164,12 @@ module Nokogiri
|
|
164
164
|
assert_match %r% \n<div>b</div> *%, fragment.to_s
|
165
165
|
end
|
166
166
|
|
167
|
+
def test_html_fragment_with_input_and_intermediate_whitespace
|
168
|
+
doc = "<label>Label</label><input type=\"text\"> <span>span</span>"
|
169
|
+
fragment = Nokogiri::HTML::Document.new.fragment(doc)
|
170
|
+
assert_equal "<label>Label</label><input type=\"text\"> <span>span</span>", fragment.to_s
|
171
|
+
end
|
172
|
+
|
167
173
|
def test_html_fragment_with_leading_text_and_newline
|
168
174
|
fragment = HTML::Document.new.fragment("First line\nSecond line<br>Broken line")
|
169
175
|
assert_equal fragment.to_s, "First line\nSecond line<br>Broken line"
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require "helper"
|
2
|
+
|
3
|
+
module Nokogiri
|
4
|
+
module XML
|
5
|
+
class TestAliasedDefaultNamespaces < Nokogiri::TestCase
|
6
|
+
def setup
|
7
|
+
super
|
8
|
+
end
|
9
|
+
|
10
|
+
def test_alised_default_namespace_on_parse
|
11
|
+
doc = Nokogiri::XML('<apple xmlns="ns:fruit" xmlns:fruit="ns:fruit" />')
|
12
|
+
ns = doc.root.namespaces
|
13
|
+
assert_equal "ns:fruit", ns["xmlns:fruit"], "Should have parsed aliased default namespace"
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_add_aliased_default_namespace
|
17
|
+
doc = Nokogiri::XML('<apple xmlns="ns:fruit" />')
|
18
|
+
doc.root.add_namespace_definition("fruit", "ns:fruit")
|
19
|
+
ns = doc.root.namespaces
|
20
|
+
assert_equal "ns:fruit", ns["xmlns:fruit"],"Should have added aliased default namespace"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require "helper"
|
2
|
+
|
3
|
+
module Nokogiri
|
4
|
+
module XML
|
5
|
+
class TestNamespacePreservation < Nokogiri::TestCase
|
6
|
+
|
7
|
+
def setup
|
8
|
+
@xml = Nokogiri.XML <<-eoxml
|
9
|
+
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
10
|
+
<xs:element xmlns:quer="http://api.geotrust.com/webtrust/query"/>
|
11
|
+
<xs:element xmlns:quer="http://api.geotrust.com/webtrust/query"/>
|
12
|
+
</xs:schema>
|
13
|
+
eoxml
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_xpath
|
17
|
+
first = @xml.at_xpath('//xs:element', 'xs' => 'http://www.w3.org/2001/XMLSchema')
|
18
|
+
last = @xml.at_xpath('//xs:element[last()]', 'xs' => 'http://www.w3.org/2001/XMLSchema')
|
19
|
+
assert_equal 'http://api.geotrust.com/webtrust/query' , first.namespaces['xmlns:quer'], "Should contain quer namespace"
|
20
|
+
assert_equal 'http://api.geotrust.com/webtrust/query' , last.namespaces['xmlns:quer'], "Should contain quer namespace"
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_traversing
|
24
|
+
first = @xml.root.element_children.first
|
25
|
+
last = @xml.root.element_children.last
|
26
|
+
assert_equal 'http://api.geotrust.com/webtrust/query' , first.namespaces['xmlns:quer'], "Should contain quer namespace"
|
27
|
+
assert_equal 'http://api.geotrust.com/webtrust/query' , last.namespaces['xmlns:quer'], "Should contain quer namespace"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
data/test/xml/test_text.rb
CHANGED
@@ -40,6 +40,21 @@ module Nokogiri
|
|
40
40
|
assert_equal('& <foo> &', node.content)
|
41
41
|
assert_equal('& <foo> &amp;', node.to_xml)
|
42
42
|
end
|
43
|
+
|
44
|
+
def test_add_child
|
45
|
+
node = Text.new('foo', Document.new)
|
46
|
+
if Nokogiri.jruby?
|
47
|
+
exc = RuntimeError
|
48
|
+
else
|
49
|
+
exc = ArgumentError
|
50
|
+
end
|
51
|
+
assert_raises(exc) {
|
52
|
+
node.add_child Text.new('bar', Document.new)
|
53
|
+
}
|
54
|
+
assert_raises(exc) {
|
55
|
+
node << Text.new('bar', Document.new)
|
56
|
+
}
|
57
|
+
end
|
43
58
|
end
|
44
59
|
end
|
45
60
|
end
|
data/test_all
CHANGED
@@ -10,7 +10,7 @@
|
|
10
10
|
# (e.g., 1.9.3's glob_helper). ["rake test:valgrind:suppression"]
|
11
11
|
#
|
12
12
|
|
13
|
-
RUBIES="ruby-1.9.3
|
13
|
+
RUBIES="ruby-1.9.3 ruby-1.9.2 ruby-2.0 ruby-2.1 jruby-1.7"
|
14
14
|
TEST_LOG=test.log
|
15
15
|
VALGRIND_LOG=valgrind.log
|
16
16
|
|
@@ -34,7 +34,7 @@ function rvm_use {
|
|
34
34
|
|
35
35
|
function generate_parser_and_tokenizer {
|
36
36
|
old_ruby=$current_ruby
|
37
|
-
rvm_use ruby-1.9.3
|
37
|
+
rvm_use ruby-1.9.3
|
38
38
|
bundle exec rake generate 2>&1 > /dev/null
|
39
39
|
rvm_use $old_ruby
|
40
40
|
}
|
@@ -51,7 +51,7 @@ function compile {
|
|
51
51
|
|
52
52
|
for ruby in $RUBIES ; do
|
53
53
|
rvm_use ${ruby}
|
54
|
-
if !
|
54
|
+
if ! [[ $(bundle -v) =~ "1.6." ]] ; then
|
55
55
|
gem install bundler
|
56
56
|
fi
|
57
57
|
bundle install --quiet --local || bundle install
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: nokogiri
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.6.2.
|
4
|
+
version: 1.6.2.rc3
|
5
5
|
platform: java
|
6
6
|
authors:
|
7
7
|
- Aaron Patterson
|
@@ -12,7 +12,7 @@ authors:
|
|
12
12
|
autorequire:
|
13
13
|
bindir: bin
|
14
14
|
cert_chain: []
|
15
|
-
date: 2014-
|
15
|
+
date: 2014-05-09 00:00:00.000000000 Z
|
16
16
|
dependencies:
|
17
17
|
- !ruby/object:Gem::Dependency
|
18
18
|
name: rdoc
|
@@ -550,10 +550,12 @@ files:
|
|
550
550
|
- test/html/test_node.rb
|
551
551
|
- test/html/test_node_encoding.rb
|
552
552
|
- test/namespaces/test_additional_namespaces_in_builder_doc.rb
|
553
|
+
- test/namespaces/test_namespaces_aliased_default.rb
|
553
554
|
- test/namespaces/test_namespaces_in_builder_doc.rb
|
554
555
|
- test/namespaces/test_namespaces_in_cloned_doc.rb
|
555
556
|
- test/namespaces/test_namespaces_in_created_doc.rb
|
556
557
|
- test/namespaces/test_namespaces_in_parsed_doc.rb
|
558
|
+
- test/namespaces/test_namespaces_preservation.rb
|
557
559
|
- test/test_convert_xpath.rb
|
558
560
|
- test/test_css_cache.rb
|
559
561
|
- test/test_encoding_handler.rb
|
@@ -692,7 +694,9 @@ test_files:
|
|
692
694
|
- test/css/test_nthiness.rb
|
693
695
|
- test/css/test_xpath_visitor.rb
|
694
696
|
- test/namespaces/test_namespaces_in_parsed_doc.rb
|
697
|
+
- test/namespaces/test_namespaces_aliased_default.rb
|
695
698
|
- test/namespaces/test_namespaces_in_cloned_doc.rb
|
699
|
+
- test/namespaces/test_namespaces_preservation.rb
|
696
700
|
- test/namespaces/test_namespaces_in_created_doc.rb
|
697
701
|
- test/namespaces/test_additional_namespaces_in_builder_doc.rb
|
698
702
|
- test/namespaces/test_namespaces_in_builder_doc.rb
|