nokogiri 1.11.1-java → 1.11.2-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.

Files changed (142) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE-DEPENDENCIES.md +12 -12
  3. data/LICENSE.md +1 -1
  4. data/README.md +20 -15
  5. data/ext/java/nokogiri/EncodingHandler.java +78 -59
  6. data/ext/java/nokogiri/HtmlDocument.java +137 -114
  7. data/ext/java/nokogiri/HtmlElementDescription.java +104 -87
  8. data/ext/java/nokogiri/HtmlEntityLookup.java +31 -26
  9. data/ext/java/nokogiri/HtmlSaxParserContext.java +220 -192
  10. data/ext/java/nokogiri/HtmlSaxPushParser.java +164 -139
  11. data/ext/java/nokogiri/NokogiriService.java +597 -526
  12. data/ext/java/nokogiri/XmlAttr.java +120 -96
  13. data/ext/java/nokogiri/XmlAttributeDecl.java +97 -76
  14. data/ext/java/nokogiri/XmlCdata.java +35 -26
  15. data/ext/java/nokogiri/XmlComment.java +48 -37
  16. data/ext/java/nokogiri/XmlDocument.java +642 -540
  17. data/ext/java/nokogiri/XmlDocumentFragment.java +127 -107
  18. data/ext/java/nokogiri/XmlDtd.java +450 -384
  19. data/ext/java/nokogiri/XmlElement.java +25 -18
  20. data/ext/java/nokogiri/XmlElementContent.java +345 -286
  21. data/ext/java/nokogiri/XmlElementDecl.java +126 -95
  22. data/ext/java/nokogiri/XmlEntityDecl.java +121 -97
  23. data/ext/java/nokogiri/XmlEntityReference.java +51 -42
  24. data/ext/java/nokogiri/XmlNamespace.java +177 -145
  25. data/ext/java/nokogiri/XmlNode.java +1843 -1588
  26. data/ext/java/nokogiri/XmlNodeSet.java +361 -299
  27. data/ext/java/nokogiri/XmlProcessingInstruction.java +49 -39
  28. data/ext/java/nokogiri/XmlReader.java +513 -418
  29. data/ext/java/nokogiri/XmlRelaxng.java +91 -78
  30. data/ext/java/nokogiri/XmlSaxParserContext.java +330 -285
  31. data/ext/java/nokogiri/XmlSaxPushParser.java +229 -190
  32. data/ext/java/nokogiri/XmlSchema.java +328 -263
  33. data/ext/java/nokogiri/XmlSyntaxError.java +113 -83
  34. data/ext/java/nokogiri/XmlText.java +57 -46
  35. data/ext/java/nokogiri/XmlXpathContext.java +240 -206
  36. data/ext/java/nokogiri/XsltStylesheet.java +282 -239
  37. data/ext/java/nokogiri/internals/ClosedStreamException.java +5 -2
  38. data/ext/java/nokogiri/internals/HtmlDomParserContext.java +199 -168
  39. data/ext/java/nokogiri/internals/IgnoreSchemaErrorsErrorHandler.java +17 -10
  40. data/ext/java/nokogiri/internals/NokogiriBlockingQueueInputStream.java +43 -16
  41. data/ext/java/nokogiri/internals/NokogiriDomParser.java +65 -50
  42. data/ext/java/nokogiri/internals/NokogiriEntityResolver.java +107 -88
  43. data/ext/java/nokogiri/internals/NokogiriErrorHandler.java +25 -18
  44. data/ext/java/nokogiri/internals/NokogiriHandler.java +316 -254
  45. data/ext/java/nokogiri/internals/NokogiriHelpers.java +738 -622
  46. data/ext/java/nokogiri/internals/NokogiriNamespaceCache.java +186 -143
  47. data/ext/java/nokogiri/internals/NokogiriNamespaceContext.java +83 -68
  48. data/ext/java/nokogiri/internals/NokogiriNonStrictErrorHandler.java +66 -49
  49. data/ext/java/nokogiri/internals/NokogiriNonStrictErrorHandler4NekoHtml.java +86 -69
  50. data/ext/java/nokogiri/internals/NokogiriStrictErrorHandler.java +44 -29
  51. data/ext/java/nokogiri/internals/NokogiriXPathFunction.java +118 -101
  52. data/ext/java/nokogiri/internals/NokogiriXPathFunctionResolver.java +34 -24
  53. data/ext/java/nokogiri/internals/NokogiriXPathVariableResolver.java +25 -17
  54. data/ext/java/nokogiri/internals/NokogiriXsltErrorListener.java +57 -42
  55. data/ext/java/nokogiri/internals/ParserContext.java +206 -179
  56. data/ext/java/nokogiri/internals/ReaderNode.java +478 -371
  57. data/ext/java/nokogiri/internals/SaveContextVisitor.java +822 -707
  58. data/ext/java/nokogiri/internals/SchemaErrorHandler.java +28 -19
  59. data/ext/java/nokogiri/internals/XalanDTMManagerPatch.java +129 -123
  60. data/ext/java/nokogiri/internals/XmlDeclHandler.java +5 -4
  61. data/ext/java/nokogiri/internals/XmlDomParserContext.java +208 -177
  62. data/ext/java/nokogiri/internals/XmlSaxParser.java +24 -17
  63. data/ext/java/nokogiri/internals/c14n/AttrCompare.java +71 -68
  64. data/ext/java/nokogiri/internals/c14n/C14nHelper.java +137 -118
  65. data/ext/java/nokogiri/internals/c14n/CanonicalFilter.java +27 -21
  66. data/ext/java/nokogiri/internals/c14n/CanonicalizationException.java +74 -61
  67. data/ext/java/nokogiri/internals/c14n/Canonicalizer.java +230 -205
  68. data/ext/java/nokogiri/internals/c14n/Canonicalizer11.java +572 -547
  69. data/ext/java/nokogiri/internals/c14n/Canonicalizer11_OmitComments.java +17 -10
  70. data/ext/java/nokogiri/internals/c14n/Canonicalizer11_WithComments.java +17 -10
  71. data/ext/java/nokogiri/internals/c14n/Canonicalizer20010315.java +323 -302
  72. data/ext/java/nokogiri/internals/c14n/Canonicalizer20010315Excl.java +232 -219
  73. data/ext/java/nokogiri/internals/c14n/Canonicalizer20010315ExclOmitComments.java +22 -15
  74. data/ext/java/nokogiri/internals/c14n/Canonicalizer20010315ExclWithComments.java +23 -16
  75. data/ext/java/nokogiri/internals/c14n/Canonicalizer20010315OmitComments.java +23 -16
  76. data/ext/java/nokogiri/internals/c14n/Canonicalizer20010315WithComments.java +22 -15
  77. data/ext/java/nokogiri/internals/c14n/CanonicalizerBase.java +575 -545
  78. data/ext/java/nokogiri/internals/c14n/CanonicalizerPhysical.java +141 -120
  79. data/ext/java/nokogiri/internals/c14n/CanonicalizerSpi.java +39 -38
  80. data/ext/java/nokogiri/internals/c14n/Constants.java +13 -10
  81. data/ext/java/nokogiri/internals/c14n/ElementProxy.java +279 -247
  82. data/ext/java/nokogiri/internals/c14n/HelperNodeList.java +66 -53
  83. data/ext/java/nokogiri/internals/c14n/IgnoreAllErrorHandler.java +44 -37
  84. data/ext/java/nokogiri/internals/c14n/InclusiveNamespaces.java +135 -120
  85. data/ext/java/nokogiri/internals/c14n/InvalidCanonicalizerException.java +59 -48
  86. data/ext/java/nokogiri/internals/c14n/NameSpaceSymbTable.java +384 -334
  87. data/ext/java/nokogiri/internals/c14n/NodeFilter.java +25 -24
  88. data/ext/java/nokogiri/internals/c14n/UtfHelpper.java +151 -140
  89. data/ext/java/nokogiri/internals/c14n/XMLUtils.java +456 -423
  90. data/ext/java/nokogiri/internals/dom2dtm/DOM2DTM.java +1466 -1500
  91. data/ext/java/nokogiri/internals/dom2dtm/DOM2DTMdefaultNamespaceDeclarationNode.java +626 -570
  92. data/ext/nokogiri/depend +34 -474
  93. data/ext/nokogiri/extconf.rb +253 -183
  94. data/ext/nokogiri/html_document.c +10 -15
  95. data/ext/nokogiri/html_element_description.c +84 -71
  96. data/ext/nokogiri/html_entity_lookup.c +21 -16
  97. data/ext/nokogiri/html_sax_parser_context.c +66 -65
  98. data/ext/nokogiri/html_sax_push_parser.c +29 -27
  99. data/ext/nokogiri/libxml2_backwards_compat.c +121 -0
  100. data/ext/nokogiri/nokogiri.c +171 -63
  101. data/ext/nokogiri/test_global_handlers.c +3 -4
  102. data/ext/nokogiri/xml_attr.c +15 -15
  103. data/ext/nokogiri/xml_attribute_decl.c +18 -18
  104. data/ext/nokogiri/xml_cdata.c +13 -18
  105. data/ext/nokogiri/xml_comment.c +19 -26
  106. data/ext/nokogiri/xml_document.c +221 -164
  107. data/ext/nokogiri/xml_document_fragment.c +13 -15
  108. data/ext/nokogiri/xml_dtd.c +54 -48
  109. data/ext/nokogiri/xml_element_content.c +30 -27
  110. data/ext/nokogiri/xml_element_decl.c +22 -22
  111. data/ext/nokogiri/xml_encoding_handler.c +17 -11
  112. data/ext/nokogiri/xml_entity_decl.c +32 -30
  113. data/ext/nokogiri/xml_entity_reference.c +16 -18
  114. data/ext/nokogiri/xml_namespace.c +56 -49
  115. data/ext/nokogiri/xml_node.c +338 -286
  116. data/ext/nokogiri/xml_node_set.c +168 -156
  117. data/ext/nokogiri/xml_processing_instruction.c +17 -19
  118. data/ext/nokogiri/xml_reader.c +191 -157
  119. data/ext/nokogiri/xml_relax_ng.c +29 -23
  120. data/ext/nokogiri/xml_sax_parser.c +117 -112
  121. data/ext/nokogiri/xml_sax_parser_context.c +100 -85
  122. data/ext/nokogiri/xml_sax_push_parser.c +34 -27
  123. data/ext/nokogiri/xml_schema.c +48 -42
  124. data/ext/nokogiri/xml_syntax_error.c +21 -23
  125. data/ext/nokogiri/xml_text.c +13 -17
  126. data/ext/nokogiri/xml_xpath_context.c +134 -127
  127. data/ext/nokogiri/xslt_stylesheet.c +157 -157
  128. data/lib/nokogiri.rb +1 -22
  129. data/lib/nokogiri/css/parser.rb +1 -1
  130. data/lib/nokogiri/extension.rb +26 -0
  131. data/lib/nokogiri/html/document_fragment.rb +15 -15
  132. data/lib/nokogiri/nokogiri.jar +0 -0
  133. data/lib/nokogiri/version/constant.rb +1 -1
  134. data/lib/nokogiri/version/info.rb +31 -8
  135. data/lib/nokogiri/xml/document.rb +31 -11
  136. data/lib/nokogiri/xml/node.rb +38 -42
  137. data/lib/nokogiri/xml/reader.rb +2 -9
  138. data/lib/nokogiri/xml/xpath.rb +1 -3
  139. data/lib/nokogiri/xml/xpath/syntax_error.rb +1 -1
  140. metadata +7 -8
  141. data/ext/nokogiri/xml_io.c +0 -63
  142. data/ext/nokogiri/xml_libxml2_hacks.c +0 -112
@@ -17,10 +17,10 @@
17
17
  * distribute, sublicense, and/or sell copies of the Software, and to
18
18
  * permit persons to whom the Software is furnished to do so, subject to
19
19
  * the following conditions:
20
- *
20
+ *
21
21
  * The above copyright notice and this permission notice shall be
22
22
  * included in all copies or substantial portions of the Software.
23
- *
23
+ *
24
24
  * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
25
25
  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26
26
  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
@@ -58,128 +58,148 @@ import org.w3c.dom.NamedNodeMap;
58
58
 
59
59
  /**
60
60
  * Class for Nokogiri::XML::DocumentFragment
61
- *
61
+ *
62
62
  * @author sergio
63
63
  * @author Yoko Harada <yokolet@gmail.com>
64
64
  */
65
- @JRubyClass(name="Nokogiri::XML::DocumentFragment", parent="Nokogiri::XML::Node")
66
- public class XmlDocumentFragment extends XmlNode {
67
-
68
- private XmlElement fragmentContext;
69
-
70
- public XmlDocumentFragment(Ruby ruby) {
71
- this(ruby, getNokogiriClass(ruby, "Nokogiri::XML::DocumentFragment"));
65
+ @JRubyClass(name = "Nokogiri::XML::DocumentFragment", parent = "Nokogiri::XML::Node")
66
+ public class XmlDocumentFragment extends XmlNode
67
+ {
68
+
69
+ private XmlElement fragmentContext;
70
+
71
+ public
72
+ XmlDocumentFragment(Ruby ruby)
73
+ {
74
+ this(ruby, getNokogiriClass(ruby, "Nokogiri::XML::DocumentFragment"));
75
+ }
76
+
77
+ public
78
+ XmlDocumentFragment(Ruby ruby, RubyClass klazz)
79
+ {
80
+ super(ruby, klazz);
81
+ }
82
+
83
+ @JRubyMethod(name = "new", meta = true, required = 1, optional = 2)
84
+ public static IRubyObject
85
+ rbNew(ThreadContext context, IRubyObject cls, IRubyObject[] args)
86
+ {
87
+ if (args.length < 1) {
88
+ throw context.runtime.newArgumentError(args.length, 1);
72
89
  }
73
90
 
74
- public XmlDocumentFragment(Ruby ruby, RubyClass klazz) {
75
- super(ruby, klazz);
91
+ if (!(args[0] instanceof XmlDocument)) {
92
+ throw context.runtime.newArgumentError("first parameter must be a Nokogiri::XML::Document instance");
76
93
  }
77
94
 
78
- @JRubyMethod(name="new", meta = true, required=1, optional=2)
79
- public static IRubyObject rbNew(ThreadContext context, IRubyObject cls, IRubyObject[] args) {
80
- if (args.length < 1) {
81
- throw context.runtime.newArgumentError(args.length, 1);
82
- }
83
-
84
- if (!(args[0] instanceof XmlDocument)){
85
- throw context.runtime.newArgumentError("first parameter must be a Nokogiri::XML::Document instance");
86
- }
87
-
88
- XmlDocument doc = (XmlDocument) args[0];
89
-
90
- // make wellformed fragment, ignore invalid namespace, or add appropriate namespace to parse
91
- if (args.length > 1 && args[1] instanceof RubyString) {
92
- final RubyString arg1 = (RubyString) args[1];
93
- if (XmlDocumentFragment.isTag(arg1)) {
94
- args[1] = RubyString.newString(context.runtime, addNamespaceDeclIfNeeded(doc, rubyStringToString(arg1)));
95
- }
96
- }
97
-
98
- XmlDocumentFragment fragment = (XmlDocumentFragment) NokogiriService.XML_DOCUMENT_FRAGMENT_ALLOCATOR.allocate(context.runtime, (RubyClass)cls);
99
- fragment.setDocument(context, doc);
100
- fragment.setNode(context.runtime, doc.getDocument().createDocumentFragment());
95
+ XmlDocument doc = (XmlDocument) args[0];
101
96
 
102
- //TODO: Get namespace definitions from doc.
103
- if (args.length == 3 && args[2] != null && args[2] instanceof XmlElement) {
104
- fragment.fragmentContext = (XmlElement)args[2];
105
- }
106
- Helpers.invoke(context, fragment, "initialize", args);
107
- return fragment;
97
+ // make wellformed fragment, ignore invalid namespace, or add appropriate namespace to parse
98
+ if (args.length > 1 && args[1] instanceof RubyString) {
99
+ final RubyString arg1 = (RubyString) args[1];
100
+ if (XmlDocumentFragment.isTag(arg1)) {
101
+ args[1] = RubyString.newString(context.runtime, addNamespaceDeclIfNeeded(doc, rubyStringToString(arg1)));
102
+ }
108
103
  }
109
104
 
110
- private static final ByteList TAG_BEG = ByteList.create("<");
111
- private static final ByteList TAG_END = ByteList.create(">");
105
+ XmlDocumentFragment fragment = (XmlDocumentFragment) NokogiriService.XML_DOCUMENT_FRAGMENT_ALLOCATOR.allocate(
106
+ context.runtime, (RubyClass)cls);
107
+ fragment.setDocument(context, doc);
108
+ fragment.setNode(context.runtime, doc.getDocument().createDocumentFragment());
112
109
 
113
- private static boolean isTag(final RubyString str) {
114
- return str.getByteList().startsWith(TAG_BEG) && str.getByteList().endsWith(TAG_END);
110
+ //TODO: Get namespace definitions from doc.
111
+ if (args.length == 3 && args[2] != null && args[2] instanceof XmlElement) {
112
+ fragment.fragmentContext = (XmlElement)args[2];
115
113
  }
116
-
117
- private static boolean isNamespaceDefined(String qName, NamedNodeMap nodeMap) {
118
- if (isNamespace(qName.intern())) return true;
119
- for (int i=0; i < nodeMap.getLength(); i++) {
120
- Attr attr = (Attr)nodeMap.item(i);
121
- if (isNamespace(attr.getNodeName())) {
122
- String localPart = getLocalNameForNamespace(attr.getNodeName(), null);
123
- if (getPrefix(qName).equals(localPart)) {
124
- return true;
125
- }
126
- }
114
+ Helpers.invoke(context, fragment, "initialize", args);
115
+ return fragment;
116
+ }
117
+
118
+ private static final ByteList TAG_BEG = ByteList.create("<");
119
+ private static final ByteList TAG_END = ByteList.create(">");
120
+
121
+ private static boolean
122
+ isTag(final RubyString str)
123
+ {
124
+ return str.getByteList().startsWith(TAG_BEG) && str.getByteList().endsWith(TAG_END);
125
+ }
126
+
127
+ private static boolean
128
+ isNamespaceDefined(String qName, NamedNodeMap nodeMap)
129
+ {
130
+ if (isNamespace(qName.intern())) { return true; }
131
+ for (int i = 0; i < nodeMap.getLength(); i++) {
132
+ Attr attr = (Attr)nodeMap.item(i);
133
+ if (isNamespace(attr.getNodeName())) {
134
+ String localPart = getLocalNameForNamespace(attr.getNodeName(), null);
135
+ if (getPrefix(qName).equals(localPart)) {
136
+ return true;
127
137
  }
128
- return false;
138
+ }
129
139
  }
130
-
131
- private static final Pattern QNAME_RE = Pattern.compile("[^</:>\\s]+:[^</:>=\\s]+");
132
- private static final Pattern START_TAG_RE = Pattern.compile("<[^</>]+>");
133
-
134
- private static String addNamespaceDeclIfNeeded(XmlDocument doc, String tags) {
135
- if (doc.getDocument() == null) return tags;
136
- if (doc.getDocument().getDocumentElement() == null) return tags;
137
- Matcher matcher = START_TAG_RE.matcher(tags);
138
- Map<CharSequence, CharSequence> rewriteTable = null;
139
- while (matcher.find()) {
140
- String start_tag = matcher.group();
141
- Matcher matcher2 = QNAME_RE.matcher(start_tag);
142
- while (matcher2.find()) {
143
- String qName = matcher2.group();
144
- NamedNodeMap nodeMap = doc.getDocument().getDocumentElement().getAttributes();
145
- if (isNamespaceDefined(qName, nodeMap)) {
146
- CharSequence namespaceDecl = getNamespaceDecl(getPrefix(qName), nodeMap);
147
- if (namespaceDecl != null) {
148
- if (rewriteTable == null) rewriteTable = new HashMap(8, 1);
149
- StringBuilder str = new StringBuilder(qName.length() + namespaceDecl.length() + 3);
150
- String key = str.append('<').append(qName).append('>').toString();
151
- str.setCharAt(key.length() - 1, ' '); // (last) '>' -> ' '
152
- rewriteTable.put(key, str.append(namespaceDecl).append('>'));
153
- }
154
- }
155
- }
140
+ return false;
141
+ }
142
+
143
+ private static final Pattern QNAME_RE = Pattern.compile("[^</:>\\s]+:[^</:>=\\s]+");
144
+ private static final Pattern START_TAG_RE = Pattern.compile("<[^</>]+>");
145
+
146
+ private static String
147
+ addNamespaceDeclIfNeeded(XmlDocument doc, String tags)
148
+ {
149
+ if (doc.getDocument() == null) { return tags; }
150
+ if (doc.getDocument().getDocumentElement() == null) { return tags; }
151
+ Matcher matcher = START_TAG_RE.matcher(tags);
152
+ Map<CharSequence, CharSequence> rewriteTable = null;
153
+ while (matcher.find()) {
154
+ String start_tag = matcher.group();
155
+ Matcher matcher2 = QNAME_RE.matcher(start_tag);
156
+ while (matcher2.find()) {
157
+ String qName = matcher2.group();
158
+ NamedNodeMap nodeMap = doc.getDocument().getDocumentElement().getAttributes();
159
+ if (isNamespaceDefined(qName, nodeMap)) {
160
+ CharSequence namespaceDecl = getNamespaceDecl(getPrefix(qName), nodeMap);
161
+ if (namespaceDecl != null) {
162
+ if (rewriteTable == null) { rewriteTable = new HashMap(8, 1); }
163
+ StringBuilder str = new StringBuilder(qName.length() + namespaceDecl.length() + 3);
164
+ String key = str.append('<').append(qName).append('>').toString();
165
+ str.setCharAt(key.length() - 1, ' '); // (last) '>' -> ' '
166
+ rewriteTable.put(key, str.append(namespaceDecl).append('>'));
167
+ }
156
168
  }
157
- if (rewriteTable != null) {
158
- for (Map.Entry<CharSequence, CharSequence> e : rewriteTable.entrySet()) {
159
- tags = tags.replace(e.getKey(), e.getValue());
160
- }
161
- }
162
-
163
- return tags;
164
- }
165
-
166
- private static CharSequence getNamespaceDecl(final String prefix, NamedNodeMap nodeMap) {
167
- for (int i=0; i < nodeMap.getLength(); i++) {
168
- Attr attr = (Attr) nodeMap.item(i);
169
- if (prefix.equals(attr.getLocalName())) {
170
- return new StringBuilder().
171
- append(attr.getName()).append('=').append('"').append(attr.getValue()).append('"');
172
- }
173
- }
174
- return null;
169
+ }
175
170
  }
176
-
177
- public XmlElement getFragmentContext() {
178
- return fragmentContext;
171
+ if (rewriteTable != null) {
172
+ for (Map.Entry<CharSequence, CharSequence> e : rewriteTable.entrySet()) {
173
+ tags = tags.replace(e.getKey(), e.getValue());
174
+ }
179
175
  }
180
176
 
181
- @Override
182
- public void relink_namespace(ThreadContext context) {
183
- relink_namespace(context, getChildren());
177
+ return tags;
178
+ }
179
+
180
+ private static CharSequence
181
+ getNamespaceDecl(final String prefix, NamedNodeMap nodeMap)
182
+ {
183
+ for (int i = 0; i < nodeMap.getLength(); i++) {
184
+ Attr attr = (Attr) nodeMap.item(i);
185
+ if (prefix.equals(attr.getLocalName())) {
186
+ return new StringBuilder().
187
+ append(attr.getName()).append('=').append('"').append(attr.getValue()).append('"');
188
+ }
184
189
  }
190
+ return null;
191
+ }
192
+
193
+ public XmlElement
194
+ getFragmentContext()
195
+ {
196
+ return fragmentContext;
197
+ }
198
+
199
+ @Override
200
+ public void
201
+ relink_namespace(ThreadContext context)
202
+ {
203
+ relink_namespace(context, getChildren());
204
+ }
185
205
  }
@@ -17,10 +17,10 @@
17
17
  * distribute, sublicense, and/or sell copies of the Software, and to
18
18
  * permit persons to whom the Software is furnished to do so, subject to
19
19
  * the following conditions:
20
- *
20
+ *
21
21
  * The above copyright notice and this permission notice shall be
22
22
  * included in all copies or substantial portions of the Software.
23
- *
23
+ *
24
24
  * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
25
25
  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26
26
  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
@@ -61,421 +61,487 @@ import nokogiri.internals.SaveContextVisitor;
61
61
 
62
62
  /**
63
63
  * Class for Nokogiri::XML::DTD
64
- *
64
+ *
65
65
  * @author sergio
66
66
  * @author Patrick Mahoney <pat@polycrystal.org>
67
67
  * @author Yoko Harada <yokolet@gmail.com>
68
68
  */
69
69
 
70
- @JRubyClass(name="Nokogiri::XML::DTD", parent="Nokogiri::XML::Node")
71
- public class XmlDtd extends XmlNode {
72
- /** cache of children, Nokogiri::XML::NodeSet */
73
- protected IRubyObject children = null;
74
-
75
- /** cache of name => XmlAttributeDecl */
76
- protected RubyHash attributes = null;
77
-
78
- /** cache of name => XmlElementDecl */
79
- protected RubyHash elements = null;
80
-
81
- /** cache of name => XmlEntityDecl */
82
- protected RubyHash entities = null;
83
-
84
- /** cache of name => Nokogiri::XML::Notation */
85
- protected RubyHash notations = null;
86
- protected RubyClass notationClass;
87
-
88
- /** temporary store of content models before they are added to
89
- * their XmlElementDecl. */
90
- protected RubyHash contentModels;
91
-
92
- /** node name */
93
- protected IRubyObject name;
94
-
95
- /** public ID (or external ID) */
96
- protected IRubyObject pubId;
97
-
98
- /** system ID */
99
- protected IRubyObject sysId;
100
-
101
- public XmlDtd(Ruby ruby, RubyClass rubyClass) {
102
- super(ruby, rubyClass);
103
- }
104
-
105
- public void setNode(Ruby runtime, Node dtd) {
106
- this.node = dtd;
107
- notationClass = (RubyClass) runtime.getClassFromPath("Nokogiri::XML::Notation");
108
-
109
- name = pubId = sysId = runtime.getNil();
110
- if (dtd == null) return;
111
-
112
- // This is the dtd declaration stored in the document; it
113
- // contains the DTD name (root element) and public and system
114
- // ids. The actual declarations are in the NekoDTD 'dtd'
115
- // variable. I don't know of a way to consolidate the two.
116
-
117
- DocumentType otherDtd = dtd.getOwnerDocument().getDoctype();
118
- if (otherDtd != null) {
119
- name = stringOrNil(runtime, otherDtd.getNodeName());
120
- pubId = nonEmptyStringOrNil(runtime, otherDtd.getPublicId());
121
- sysId = nonEmptyStringOrNil(runtime, otherDtd.getSystemId());
122
- }
123
- }
124
-
125
- public XmlDtd(Ruby ruby, RubyClass rubyClass, Node dtd) {
126
- super(ruby, rubyClass, dtd);
127
- setNode(ruby, dtd);
128
- }
129
-
130
- public static XmlDtd newEmpty(Ruby runtime,
131
- Document doc,
132
- IRubyObject name,
133
- IRubyObject external_id,
134
- IRubyObject system_id) {
135
-
136
- DocumentType placeholder;
137
- if (doc.getDoctype() == null) {
138
- String javaName = NokogiriHelpers.rubyStringToString(name);
139
- String javaExternalId = NokogiriHelpers.rubyStringToString(external_id);
140
- String javaSystemId = NokogiriHelpers.rubyStringToString(system_id);
141
- placeholder = doc.getImplementation().createDocumentType(javaName, javaExternalId, javaSystemId);
142
- doc.appendChild(placeholder);
143
- } else {
144
- placeholder = doc.getDoctype();
145
- }
146
- // FIXME: what if the document had a doc type, why are we here ?
147
- XmlDtd dtd = (XmlDtd) NokogiriService.XML_DTD_ALLOCATOR.allocate(runtime, getNokogiriClass(runtime, "Nokogiri::XML::DTD"));
148
- dtd.setNode(runtime, placeholder);
149
- dtd.name = name;
150
- dtd.pubId = external_id;
151
- dtd.sysId = system_id;
152
- return dtd;
153
- }
154
-
155
-
156
- /**
157
- * Create an unparented element that contains DTD declarations
158
- * parsed from the internal subset attached as user data to
159
- * <code>doc</code>. The attached dtd must be the tree from
160
- * NekoDTD. The owner document of the returned tree will be
161
- * <code>doc</doc>.
162
- *
163
- * NekoDTD parser returns a new document node containing elements
164
- * representing the dtd declarations. The plan is to get the root
165
- * element and adopt it into the correct document, stipping the
166
- * Document provided by NekoDTD.
167
- *
168
- */
169
- public static XmlDtd newFromInternalSubset(Ruby runtime, Document doc) {
170
- Object dtdTree_ = doc.getUserData(XmlDocument.DTD_RAW_DOCUMENT);
171
- if (dtdTree_ == null) {
172
- XmlDtd xmlDtd = (XmlDtd) NokogiriService.XML_DTD_ALLOCATOR.allocate(runtime, getNokogiriClass(runtime, "Nokogiri::XML::DTD"));
173
- xmlDtd.setNode(runtime, null);
174
- return xmlDtd;
175
- }
176
-
177
- Node dtdTree = (Node) dtdTree_;
178
- Node dtd = getInternalSubset(dtdTree);
179
- if (dtd == null) {
180
- XmlDtd xmlDtd = (XmlDtd) NokogiriService.XML_DTD_ALLOCATOR.allocate(runtime, getNokogiriClass(runtime, "Nokogiri::XML::DTD"));
181
- xmlDtd.setNode(runtime, null);
182
- return xmlDtd;
183
- } else {
184
- // Import the node into doc so it has the correct owner document.
185
- dtd = doc.importNode(dtd, true);
186
- XmlDtd xmlDtd = (XmlDtd) NokogiriService.XML_DTD_ALLOCATOR.allocate(runtime, getNokogiriClass(runtime, "Nokogiri::XML::DTD"));
187
- xmlDtd.setNode(runtime, dtd);
188
- return xmlDtd;
189
- }
190
- }
191
-
192
- public static IRubyObject newFromExternalSubset(Ruby runtime, Document doc) {
193
- Object dtdTree_ = doc.getUserData(XmlDocument.DTD_RAW_DOCUMENT);
194
- if (dtdTree_ == null) {
195
- return runtime.getNil();
196
- }
197
-
198
- Node dtdTree = (Node) dtdTree_;
199
- Node dtd = getExternalSubset(dtdTree);
200
- if (dtd == null) {
201
- return runtime.getNil();
202
- } else if (!dtd.hasChildNodes()) {
203
- return runtime.getNil();
204
- } else {
205
- // Import the node into doc so it has the correct owner document.
206
- dtd = doc.importNode(dtd, true);
207
- XmlDtd xmlDtd = (XmlDtd) NokogiriService.XML_DTD_ALLOCATOR.allocate(runtime, getNokogiriClass(runtime, "Nokogiri::XML::DTD"));
208
- xmlDtd.setNode(runtime, dtd);
209
- return xmlDtd;
210
- }
211
- }
70
+ @JRubyClass(name = "Nokogiri::XML::DTD", parent = "Nokogiri::XML::Node")
71
+ public class XmlDtd extends XmlNode
72
+ {
73
+ /** cache of children, Nokogiri::XML::NodeSet */
74
+ protected IRubyObject children = null;
212
75
 
213
- /*
214
- * <code>dtd</code> is the document node of a NekoDTD tree.
215
- * NekoDTD tree looks like this:
216
- *
217
- * <code><pre>
218
- * [#document: null]
219
- * [#comment: ...]
220
- * [#comment: ...]
221
- * [dtd: null] // a DocumentType; isDTD(node) => false
222
- * [dtd: null] // root of dtd, an Element node; isDTD(node) => true
223
- * ... decls, content models, etc. ...
224
- * [externalSubset: null] pubid="the pubid" sysid="the sysid"
225
- * ... external subset decls, etc. ...
226
- * </pre></code>
227
- */
228
- protected static Node getInternalSubset(Node dtdTree) {
229
- Node root;
230
- for (root = dtdTree.getFirstChild(); ; root = root.getNextSibling()) {
231
- if (root == null)
232
- return null;
233
- else if (isDTD(root))
234
- return root; // we have second dtd which is root
235
- }
236
- }
76
+ /** cache of name => XmlAttributeDecl */
77
+ protected RubyHash attributes = null;
237
78
 
238
- protected static Node getExternalSubset(Node dtdTree) {
239
- Node dtd = getInternalSubset(dtdTree);
240
- if (dtd == null) return null;
241
- for (Node ext = dtd.getFirstChild(); ; ext = ext.getNextSibling()) {
242
- if (ext == null)
243
- return null;
244
- else if (isExternalSubset(ext))
245
- return ext;
246
- }
247
- }
79
+ /** cache of name => XmlElementDecl */
80
+ protected RubyHash elements = null;
248
81
 
249
- /**
250
- * This overrides the #attributes method defined in
251
- * lib/nokogiri/xml/node.rb.
252
- */
253
- @JRubyMethod
254
- public IRubyObject attributes(ThreadContext context) {
255
- if (attributes == null) extractDecls(context);
82
+ /** cache of name => XmlEntityDecl */
83
+ protected RubyHash entities = null;
256
84
 
257
- return attributes;
258
- }
85
+ /** cache of name => Nokogiri::XML::Notation */
86
+ protected RubyHash notations = null;
87
+ protected RubyClass notationClass;
259
88
 
260
- @JRubyMethod
261
- public IRubyObject elements(ThreadContext context) {
262
- if (elements == null) extractDecls(context);
89
+ /** temporary store of content models before they are added to
90
+ * their XmlElementDecl. */
91
+ protected RubyHash contentModels;
263
92
 
264
- return elements;
265
- }
93
+ /** node name */
94
+ protected IRubyObject name;
266
95
 
267
- @JRubyMethod
268
- public IRubyObject entities(ThreadContext context) {
269
- if (entities == null) extractDecls(context);
96
+ /** public ID (or external ID) */
97
+ protected IRubyObject pubId;
270
98
 
271
- return entities;
272
- }
99
+ /** system ID */
100
+ protected IRubyObject sysId;
273
101
 
274
- @JRubyMethod
275
- public IRubyObject notations(ThreadContext context) {
276
- if (notations == null) extractDecls(context);
102
+ public
103
+ XmlDtd(Ruby ruby, RubyClass rubyClass)
104
+ {
105
+ super(ruby, rubyClass);
106
+ }
277
107
 
278
- return notations;
279
- }
108
+ public void
109
+ setNode(Ruby runtime, Node dtd)
110
+ {
111
+ this.node = dtd;
112
+ notationClass = (RubyClass) runtime.getClassFromPath("Nokogiri::XML::Notation");
280
113
 
281
- /**
282
- * Our "node" object is as-returned by NekoDTD. The actual
283
- * "children" that we're interested in (Attribute declarations,
284
- * etc.) are a few layers deep.
285
- */
286
- @Override
287
- @JRubyMethod
288
- public IRubyObject children(ThreadContext context) {
289
- if (children == null) extractDecls(context);
290
-
291
- return children;
292
- }
114
+ name = pubId = sysId = runtime.getNil();
115
+ if (dtd == null) { return; }
293
116
 
294
- /**
295
- * Returns the name of the dtd.
296
- */
297
- @Override
298
- @JRubyMethod
299
- public IRubyObject node_name(ThreadContext context) {
300
- return name;
301
- }
117
+ // This is the dtd declaration stored in the document; it
118
+ // contains the DTD name (root element) and public and system
119
+ // ids. The actual declarations are in the NekoDTD 'dtd'
120
+ // variable. I don't know of a way to consolidate the two.
302
121
 
303
- @Override
304
- @JRubyMethod(name = "node_name=")
305
- public IRubyObject node_name_set(ThreadContext context, IRubyObject name) {
306
- throw context.getRuntime()
307
- .newRuntimeError("cannot change name of DTD");
122
+ DocumentType otherDtd = dtd.getOwnerDocument().getDoctype();
123
+ if (otherDtd != null) {
124
+ name = stringOrNil(runtime, otherDtd.getNodeName());
125
+ pubId = nonEmptyStringOrNil(runtime, otherDtd.getPublicId());
126
+ sysId = nonEmptyStringOrNil(runtime, otherDtd.getSystemId());
308
127
  }
309
-
310
- @JRubyMethod
311
- public IRubyObject system_id(ThreadContext context) {
312
- return sysId;
128
+ }
129
+
130
+ public
131
+ XmlDtd(Ruby ruby, RubyClass rubyClass, Node dtd)
132
+ {
133
+ super(ruby, rubyClass, dtd);
134
+ setNode(ruby, dtd);
135
+ }
136
+
137
+ public static XmlDtd
138
+ newEmpty(Ruby runtime,
139
+ Document doc,
140
+ IRubyObject name,
141
+ IRubyObject external_id,
142
+ IRubyObject system_id)
143
+ {
144
+
145
+ DocumentType placeholder;
146
+ if (doc.getDoctype() == null) {
147
+ String javaName = NokogiriHelpers.rubyStringToString(name);
148
+ String javaExternalId = NokogiriHelpers.rubyStringToString(external_id);
149
+ String javaSystemId = NokogiriHelpers.rubyStringToString(system_id);
150
+ placeholder = doc.getImplementation().createDocumentType(javaName, javaExternalId, javaSystemId);
151
+ doc.appendChild(placeholder);
152
+ } else {
153
+ placeholder = doc.getDoctype();
313
154
  }
314
-
315
- @JRubyMethod
316
- public IRubyObject external_id(ThreadContext context) {
317
- return pubId;
318
- }
319
-
320
- @JRubyMethod
321
- public IRubyObject validate(ThreadContext context, IRubyObject doc) {
322
- RubyArray errors = RubyArray.newArray(context.getRuntime());
323
- if (doc instanceof XmlDocument) {
324
- errors = (RubyArray) ((XmlDocument)doc).getInstanceVariable("@errors");
325
- }
326
- return errors;
155
+ // FIXME: what if the document had a doc type, why are we here ?
156
+ XmlDtd dtd = (XmlDtd) NokogiriService.XML_DTD_ALLOCATOR.allocate(runtime, getNokogiriClass(runtime,
157
+ "Nokogiri::XML::DTD"));
158
+ dtd.setNode(runtime, placeholder);
159
+ dtd.name = name;
160
+ dtd.pubId = external_id;
161
+ dtd.sysId = system_id;
162
+ return dtd;
163
+ }
164
+
165
+
166
+ /**
167
+ * Create an unparented element that contains DTD declarations
168
+ * parsed from the internal subset attached as user data to
169
+ * <code>doc</code>. The attached dtd must be the tree from
170
+ * NekoDTD. The owner document of the returned tree will be
171
+ * <code>doc</doc>.
172
+ *
173
+ * NekoDTD parser returns a new document node containing elements
174
+ * representing the dtd declarations. The plan is to get the root
175
+ * element and adopt it into the correct document, stipping the
176
+ * Document provided by NekoDTD.
177
+ *
178
+ */
179
+ public static XmlDtd
180
+ newFromInternalSubset(Ruby runtime, Document doc)
181
+ {
182
+ Object dtdTree_ = doc.getUserData(XmlDocument.DTD_RAW_DOCUMENT);
183
+ if (dtdTree_ == null) {
184
+ XmlDtd xmlDtd = (XmlDtd) NokogiriService.XML_DTD_ALLOCATOR.allocate(runtime, getNokogiriClass(runtime,
185
+ "Nokogiri::XML::DTD"));
186
+ xmlDtd.setNode(runtime, null);
187
+ return xmlDtd;
327
188
  }
328
189
 
329
- public static boolean nameEquals(Node node, QName name) {
330
- return name.localpart.equals(node.getNodeName());
190
+ Node dtdTree = (Node) dtdTree_;
191
+ Node dtd = getInternalSubset(dtdTree);
192
+ if (dtd == null) {
193
+ XmlDtd xmlDtd = (XmlDtd) NokogiriService.XML_DTD_ALLOCATOR.allocate(runtime, getNokogiriClass(runtime,
194
+ "Nokogiri::XML::DTD"));
195
+ xmlDtd.setNode(runtime, null);
196
+ return xmlDtd;
197
+ } else {
198
+ // Import the node into doc so it has the correct owner document.
199
+ dtd = doc.importNode(dtd, true);
200
+ XmlDtd xmlDtd = (XmlDtd) NokogiriService.XML_DTD_ALLOCATOR.allocate(runtime, getNokogiriClass(runtime,
201
+ "Nokogiri::XML::DTD"));
202
+ xmlDtd.setNode(runtime, dtd);
203
+ return xmlDtd;
331
204
  }
332
-
333
- public static boolean isExternalSubset(Node node) {
334
- return nameEquals(node, DTDConfiguration.E_EXTERNAL_SUBSET);
205
+ }
206
+
207
+ public static IRubyObject
208
+ newFromExternalSubset(Ruby runtime, Document doc)
209
+ {
210
+ Object dtdTree_ = doc.getUserData(XmlDocument.DTD_RAW_DOCUMENT);
211
+ if (dtdTree_ == null) {
212
+ return runtime.getNil();
335
213
  }
336
214
 
337
- /**
338
- * Checks instanceof Element so we return false for a DocumentType
339
- * node (NekoDTD uses Element for all its nodes).
340
- */
341
- public static boolean isDTD(Node node) {
342
- return (node instanceof Element &&
343
- nameEquals(node, DTDConfiguration.E_DTD));
215
+ Node dtdTree = (Node) dtdTree_;
216
+ Node dtd = getExternalSubset(dtdTree);
217
+ if (dtd == null) {
218
+ return runtime.getNil();
219
+ } else if (!dtd.hasChildNodes()) {
220
+ return runtime.getNil();
221
+ } else {
222
+ // Import the node into doc so it has the correct owner document.
223
+ dtd = doc.importNode(dtd, true);
224
+ XmlDtd xmlDtd = (XmlDtd) NokogiriService.XML_DTD_ALLOCATOR.allocate(runtime, getNokogiriClass(runtime,
225
+ "Nokogiri::XML::DTD"));
226
+ xmlDtd.setNode(runtime, dtd);
227
+ return xmlDtd;
344
228
  }
345
-
346
- public static boolean isAttributeDecl(Node node) {
347
- return nameEquals(node, DTDConfiguration.E_ATTRIBUTE_DECL);
229
+ }
230
+
231
+ /*
232
+ * <code>dtd</code> is the document node of a NekoDTD tree.
233
+ * NekoDTD tree looks like this:
234
+ *
235
+ * <code><pre>
236
+ * [#document: null]
237
+ * [#comment: ...]
238
+ * [#comment: ...]
239
+ * [dtd: null] // a DocumentType; isDTD(node) => false
240
+ * [dtd: null] // root of dtd, an Element node; isDTD(node) => true
241
+ * ... decls, content models, etc. ...
242
+ * [externalSubset: null] pubid="the pubid" sysid="the sysid"
243
+ * ... external subset decls, etc. ...
244
+ * </pre></code>
245
+ */
246
+ protected static Node
247
+ getInternalSubset(Node dtdTree)
248
+ {
249
+ Node root;
250
+ for (root = dtdTree.getFirstChild(); ; root = root.getNextSibling()) {
251
+ if (root == null) {
252
+ return null;
253
+ } else if (isDTD(root)) {
254
+ return root; // we have second dtd which is root
255
+ }
348
256
  }
349
-
350
- public static boolean isElementDecl(Node node) {
351
- return nameEquals(node, DTDConfiguration.E_ELEMENT_DECL);
257
+ }
258
+
259
+ protected static Node
260
+ getExternalSubset(Node dtdTree)
261
+ {
262
+ Node dtd = getInternalSubset(dtdTree);
263
+ if (dtd == null) { return null; }
264
+ for (Node ext = dtd.getFirstChild(); ; ext = ext.getNextSibling()) {
265
+ if (ext == null) {
266
+ return null;
267
+ } else if (isExternalSubset(ext)) {
268
+ return ext;
269
+ }
352
270
  }
353
-
354
- public static boolean isEntityDecl(Node node) {
355
- return (nameEquals(node, DTDConfiguration.E_INTERNAL_ENTITY_DECL) ||
356
- nameEquals(node, DTDConfiguration.E_UNPARSED_ENTITY_DECL));
271
+ }
272
+
273
+ /**
274
+ * This overrides the #attributes method defined in
275
+ * lib/nokogiri/xml/node.rb.
276
+ */
277
+ @JRubyMethod
278
+ public IRubyObject
279
+ attributes(ThreadContext context)
280
+ {
281
+ if (attributes == null) { extractDecls(context); }
282
+
283
+ return attributes;
284
+ }
285
+
286
+ @JRubyMethod
287
+ public IRubyObject
288
+ elements(ThreadContext context)
289
+ {
290
+ if (elements == null) { extractDecls(context); }
291
+
292
+ return elements;
293
+ }
294
+
295
+ @JRubyMethod
296
+ public IRubyObject
297
+ entities(ThreadContext context)
298
+ {
299
+ if (entities == null) { extractDecls(context); }
300
+
301
+ return entities;
302
+ }
303
+
304
+ @JRubyMethod
305
+ public IRubyObject
306
+ notations(ThreadContext context)
307
+ {
308
+ if (notations == null) { extractDecls(context); }
309
+
310
+ return notations;
311
+ }
312
+
313
+ /**
314
+ * Our "node" object is as-returned by NekoDTD. The actual
315
+ * "children" that we're interested in (Attribute declarations,
316
+ * etc.) are a few layers deep.
317
+ */
318
+ @Override
319
+ @JRubyMethod
320
+ public IRubyObject
321
+ children(ThreadContext context)
322
+ {
323
+ if (children == null) { extractDecls(context); }
324
+
325
+ return children;
326
+ }
327
+
328
+ /**
329
+ * Returns the name of the dtd.
330
+ */
331
+ @Override
332
+ @JRubyMethod
333
+ public IRubyObject
334
+ node_name(ThreadContext context)
335
+ {
336
+ return name;
337
+ }
338
+
339
+ @Override
340
+ @JRubyMethod(name = "node_name=")
341
+ public IRubyObject
342
+ node_name_set(ThreadContext context, IRubyObject name)
343
+ {
344
+ throw context.getRuntime()
345
+ .newRuntimeError("cannot change name of DTD");
346
+ }
347
+
348
+ @JRubyMethod
349
+ public IRubyObject
350
+ system_id(ThreadContext context)
351
+ {
352
+ return sysId;
353
+ }
354
+
355
+ @JRubyMethod
356
+ public IRubyObject
357
+ external_id(ThreadContext context)
358
+ {
359
+ return pubId;
360
+ }
361
+
362
+ @JRubyMethod
363
+ public IRubyObject
364
+ validate(ThreadContext context, IRubyObject doc)
365
+ {
366
+ RubyArray errors = RubyArray.newArray(context.getRuntime());
367
+ if (doc instanceof XmlDocument) {
368
+ errors = (RubyArray)((XmlDocument)doc).getInstanceVariable("@errors");
357
369
  }
358
-
359
- public static boolean isNotationDecl(Node node) {
360
- return nameEquals(node, DTDConfiguration.E_NOTATION_DECL);
370
+ return errors;
371
+ }
372
+
373
+ public static boolean
374
+ nameEquals(Node node, QName name)
375
+ {
376
+ return name.localpart.equals(node.getNodeName());
377
+ }
378
+
379
+ public static boolean
380
+ isExternalSubset(Node node)
381
+ {
382
+ return nameEquals(node, DTDConfiguration.E_EXTERNAL_SUBSET);
383
+ }
384
+
385
+ /**
386
+ * Checks instanceof Element so we return false for a DocumentType
387
+ * node (NekoDTD uses Element for all its nodes).
388
+ */
389
+ public static boolean
390
+ isDTD(Node node)
391
+ {
392
+ return (node instanceof Element &&
393
+ nameEquals(node, DTDConfiguration.E_DTD));
394
+ }
395
+
396
+ public static boolean
397
+ isAttributeDecl(Node node)
398
+ {
399
+ return nameEquals(node, DTDConfiguration.E_ATTRIBUTE_DECL);
400
+ }
401
+
402
+ public static boolean
403
+ isElementDecl(Node node)
404
+ {
405
+ return nameEquals(node, DTDConfiguration.E_ELEMENT_DECL);
406
+ }
407
+
408
+ public static boolean
409
+ isEntityDecl(Node node)
410
+ {
411
+ return (nameEquals(node, DTDConfiguration.E_INTERNAL_ENTITY_DECL) ||
412
+ nameEquals(node, DTDConfiguration.E_UNPARSED_ENTITY_DECL));
413
+ }
414
+
415
+ public static boolean
416
+ isNotationDecl(Node node)
417
+ {
418
+ return nameEquals(node, DTDConfiguration.E_NOTATION_DECL);
419
+ }
420
+
421
+ public static boolean
422
+ isContentModel(Node node)
423
+ {
424
+ return nameEquals(node, DTDConfiguration.E_CONTENT_MODEL);
425
+ }
426
+
427
+ /**
428
+ * Recursively extract various DTD declarations and store them in
429
+ * the various collections.
430
+ */
431
+ protected void
432
+ extractDecls(ThreadContext context)
433
+ {
434
+ Ruby runtime = context.runtime;
435
+
436
+ // initialize data structures
437
+ attributes = RubyHash.newHash(runtime);
438
+ elements = RubyHash.newHash(runtime);
439
+ entities = RubyHash.newHash(runtime);
440
+ notations = RubyHash.newHash(runtime);
441
+ contentModels = RubyHash.newHash(runtime);
442
+ children = runtime.getNil();
443
+
444
+ // recursively extract decls
445
+ if (node == null) { return; } // leave all the decl hash's empty
446
+
447
+ // convert allDecls to a NodeSet
448
+ children = XmlNodeSet.newNodeSet(runtime, extractDecls(context, node.getFirstChild()));
449
+
450
+ // add attribute decls as attributes to the matching element decl
451
+ RubyArray keys = attributes.keys();
452
+ for (int i = 0; i < keys.getLength(); ++i) {
453
+ IRubyObject akey = keys.entry(i);
454
+ IRubyObject val;
455
+
456
+ val = attributes.op_aref(context, akey);
457
+ if (val.isNil()) { continue; }
458
+ XmlAttributeDecl attrDecl = (XmlAttributeDecl) val;
459
+ IRubyObject ekey = attrDecl.element_name(context);
460
+ val = elements.op_aref(context, ekey);
461
+ if (val.isNil()) { continue; }
462
+ XmlElementDecl elemDecl = (XmlElementDecl) val;
463
+
464
+ elemDecl.appendAttrDecl(attrDecl);
361
465
  }
362
466
 
363
- public static boolean isContentModel(Node node) {
364
- return nameEquals(node, DTDConfiguration.E_CONTENT_MODEL);
365
- }
467
+ // add content models to the matching element decl
468
+ keys = contentModels.keys();
469
+ for (int i = 0; i < keys.getLength(); ++i) {
470
+ IRubyObject key = keys.entry(i);
471
+ IRubyObject cm = contentModels.op_aref(context, key);
366
472
 
367
- /**
368
- * Recursively extract various DTD declarations and store them in
369
- * the various collections.
370
- */
371
- protected void extractDecls(ThreadContext context) {
372
- Ruby runtime = context.runtime;
373
-
374
- // initialize data structures
375
- attributes = RubyHash.newHash(runtime);
376
- elements = RubyHash.newHash(runtime);
377
- entities = RubyHash.newHash(runtime);
378
- notations = RubyHash.newHash(runtime);
379
- contentModels = RubyHash.newHash(runtime);
380
- children = runtime.getNil();
381
-
382
- // recursively extract decls
383
- if (node == null) return; // leave all the decl hash's empty
384
-
385
- // convert allDecls to a NodeSet
386
- children = XmlNodeSet.newNodeSet(runtime, extractDecls(context, node.getFirstChild()));
387
-
388
- // add attribute decls as attributes to the matching element decl
389
- RubyArray keys = attributes.keys();
390
- for (int i = 0; i < keys.getLength(); ++i) {
391
- IRubyObject akey = keys.entry(i);
392
- IRubyObject val;
393
-
394
- val = attributes.op_aref(context, akey);
395
- if (val.isNil()) continue;
396
- XmlAttributeDecl attrDecl = (XmlAttributeDecl) val;
397
- IRubyObject ekey = attrDecl.element_name(context);
398
- val = elements.op_aref(context, ekey);
399
- if (val.isNil()) continue;
400
- XmlElementDecl elemDecl = (XmlElementDecl) val;
401
-
402
- elemDecl.appendAttrDecl(attrDecl);
403
- }
404
-
405
- // add content models to the matching element decl
406
- keys = contentModels.keys();
407
- for (int i = 0; i < keys.getLength(); ++i) {
408
- IRubyObject key = keys.entry(i);
409
- IRubyObject cm = contentModels.op_aref(context, key);
410
-
411
- IRubyObject elem = elements.op_aref(context, key);
412
- if (elem.isNil()) continue;
413
- if (((XmlElementDecl)elem).isEmpty()) continue;
414
- ((XmlElementDecl) elem).setContentModel(cm);
415
- }
473
+ IRubyObject elem = elements.op_aref(context, key);
474
+ if (elem.isNil()) { continue; }
475
+ if (((XmlElementDecl)elem).isEmpty()) { continue; }
476
+ ((XmlElementDecl) elem).setContentModel(cm);
416
477
  }
417
-
418
- /**
419
- * The <code>node</code> is either the first child of the root dtd
420
- * node (as returned by getInternalSubset()) or the first child of
421
- * the external subset node (as returned by getExternalSubset()).
422
- *
423
- * This recursive function will not descend into an
424
- * 'externalSubset' node, thus for an internal subset it only
425
- * extracts nodes in the internal subset, and for an external
426
- * subset it extracts everything and assumess <code>node</code>
427
- * and all children are part of the external subset.
428
- */
429
- protected IRubyObject[] extractDecls(ThreadContext context, Node node) {
430
- List<IRubyObject> decls = new ArrayList<IRubyObject>();
431
- while (node != null) {
432
- if (isExternalSubset(node)) {
433
- break;
434
- } else if (isAttributeDecl(node)) {
435
- XmlAttributeDecl decl = XmlAttributeDecl.create(context, node);
436
- attributes.op_aset(context, decl.attribute_name(context), decl);
437
- decls.add(decl);
438
- } else if (isElementDecl(node)) {
439
- XmlElementDecl decl = XmlElementDecl.create(context, node);
440
- elements.op_aset(context, decl.element_name(context), decl);
441
- decls.add(decl);
442
- } else if (isEntityDecl(node)) {
443
- XmlEntityDecl decl = XmlEntityDecl.create(context, node);
444
- entities.op_aset(context, decl.node_name(context), decl);
445
- decls.add(decl);
446
- } else if (isNotationDecl(node)) {
447
- XmlNode tmp = (XmlNode)
448
- NokogiriHelpers.constructNode(context.getRuntime(), node);
449
- IRubyObject decl = invoke(context, notationClass, "new",
450
- tmp.getAttribute(context, "name"),
451
- tmp.getAttribute(context, "pubid"),
452
- tmp.getAttribute(context, "sysid"));
453
- notations.op_aset(context,
454
- tmp.getAttribute(context, "name"), decl);
455
- decls.add(decl);
456
- } else if (isContentModel(node)) {
457
- XmlElementContent cm =
458
- new XmlElementContent(context.getRuntime(),
459
- (XmlDocument) document(context),
460
- node);
461
- contentModels.op_aset(context, cm.element_name(context), cm);
462
- } else {
463
- // recurse
464
- decls.addAll(Arrays.asList(extractDecls(context, node.getFirstChild())));
465
- }
466
-
467
- node = node.getNextSibling();
468
- }
469
-
470
- return decls.toArray(new IRubyObject[decls.size()]);
478
+ }
479
+
480
+ /**
481
+ * The <code>node</code> is either the first child of the root dtd
482
+ * node (as returned by getInternalSubset()) or the first child of
483
+ * the external subset node (as returned by getExternalSubset()).
484
+ *
485
+ * This recursive function will not descend into an
486
+ * 'externalSubset' node, thus for an internal subset it only
487
+ * extracts nodes in the internal subset, and for an external
488
+ * subset it extracts everything and assumess <code>node</code>
489
+ * and all children are part of the external subset.
490
+ */
491
+ protected IRubyObject[]
492
+ extractDecls(ThreadContext context, Node node)
493
+ {
494
+ List<IRubyObject> decls = new ArrayList<IRubyObject>();
495
+ while (node != null) {
496
+ if (isExternalSubset(node)) {
497
+ break;
498
+ } else if (isAttributeDecl(node)) {
499
+ XmlAttributeDecl decl = XmlAttributeDecl.create(context, node);
500
+ attributes.op_aset(context, decl.attribute_name(context), decl);
501
+ decls.add(decl);
502
+ } else if (isElementDecl(node)) {
503
+ XmlElementDecl decl = XmlElementDecl.create(context, node);
504
+ elements.op_aset(context, decl.element_name(context), decl);
505
+ decls.add(decl);
506
+ } else if (isEntityDecl(node)) {
507
+ XmlEntityDecl decl = XmlEntityDecl.create(context, node);
508
+ entities.op_aset(context, decl.node_name(context), decl);
509
+ decls.add(decl);
510
+ } else if (isNotationDecl(node)) {
511
+ XmlNode tmp = (XmlNode)
512
+ NokogiriHelpers.constructNode(context.getRuntime(), node);
513
+ IRubyObject decl = invoke(context, notationClass, "new",
514
+ tmp.getAttribute(context, "name"),
515
+ tmp.getAttribute(context, "pubid"),
516
+ tmp.getAttribute(context, "sysid"));
517
+ notations.op_aset(context,
518
+ tmp.getAttribute(context, "name"), decl);
519
+ decls.add(decl);
520
+ } else if (isContentModel(node)) {
521
+ XmlElementContent cm =
522
+ new XmlElementContent(context.getRuntime(),
523
+ (XmlDocument) document(context),
524
+ node);
525
+ contentModels.op_aset(context, cm.element_name(context), cm);
526
+ } else {
527
+ // recurse
528
+ decls.addAll(Arrays.asList(extractDecls(context, node.getFirstChild())));
529
+ }
530
+
531
+ node = node.getNextSibling();
471
532
  }
472
533
 
473
- @Override
474
- public void accept(ThreadContext context, SaveContextVisitor visitor) {
475
- // since we use nekoDTD to parse dtd, node might be ElementImpl type
476
- // An external subset doesn't need to show up, so this method just see docType.
477
- DocumentType docType = node.getOwnerDocument().getDoctype();
478
- visitor.enter(docType);
479
- visitor.leave(docType);
480
- }
534
+ return decls.toArray(new IRubyObject[decls.size()]);
535
+ }
536
+
537
+ @Override
538
+ public void
539
+ accept(ThreadContext context, SaveContextVisitor visitor)
540
+ {
541
+ // since we use nekoDTD to parse dtd, node might be ElementImpl type
542
+ // An external subset doesn't need to show up, so this method just see docType.
543
+ DocumentType docType = node.getOwnerDocument().getDoctype();
544
+ visitor.enter(docType);
545
+ visitor.leave(docType);
546
+ }
481
547
  }