nokogiri 1.5.0.beta.1-java → 1.5.0.beta.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 (117) hide show
  1. data/CHANGELOG.ja.rdoc +28 -8
  2. data/CHANGELOG.rdoc +23 -0
  3. data/Manifest.txt +68 -1
  4. data/README.ja.rdoc +1 -1
  5. data/README.rdoc +22 -4
  6. data/Rakefile +6 -2
  7. data/ext/java/nokogiri/EncodingHandler.java +92 -0
  8. data/ext/java/nokogiri/HtmlDocument.java +116 -0
  9. data/ext/java/nokogiri/HtmlElementDescription.java +111 -0
  10. data/ext/java/nokogiri/HtmlEntityLookup.java +45 -0
  11. data/ext/java/nokogiri/HtmlSaxParserContext.java +218 -0
  12. data/ext/java/nokogiri/NokogiriService.java +370 -0
  13. data/ext/java/nokogiri/XmlAttr.java +147 -0
  14. data/ext/java/nokogiri/XmlAttributeDecl.java +98 -0
  15. data/ext/java/nokogiri/XmlCdata.java +50 -0
  16. data/ext/java/nokogiri/XmlComment.java +47 -0
  17. data/ext/java/nokogiri/XmlDocument.java +463 -0
  18. data/ext/java/nokogiri/XmlDocumentFragment.java +207 -0
  19. data/ext/java/nokogiri/XmlDtd.java +427 -0
  20. data/ext/java/nokogiri/XmlElement.java +172 -0
  21. data/ext/java/nokogiri/XmlElementContent.java +350 -0
  22. data/ext/java/nokogiri/XmlElementDecl.java +115 -0
  23. data/ext/java/nokogiri/XmlEntityDecl.java +129 -0
  24. data/ext/java/nokogiri/XmlEntityReference.java +42 -0
  25. data/ext/java/nokogiri/XmlNamespace.java +77 -0
  26. data/ext/java/nokogiri/XmlNode.java +1399 -0
  27. data/ext/java/nokogiri/XmlNodeSet.java +248 -0
  28. data/ext/java/nokogiri/XmlProcessingInstruction.java +70 -0
  29. data/ext/java/nokogiri/XmlReader.java +373 -0
  30. data/ext/java/nokogiri/XmlRelaxng.java +166 -0
  31. data/ext/java/nokogiri/XmlSaxParserContext.java +308 -0
  32. data/ext/java/nokogiri/XmlSaxPushParser.java +146 -0
  33. data/ext/java/nokogiri/XmlSchema.java +142 -0
  34. data/ext/java/nokogiri/XmlSyntaxError.java +84 -0
  35. data/ext/java/nokogiri/XmlText.java +96 -0
  36. data/ext/java/nokogiri/XmlXpathContext.java +130 -0
  37. data/ext/java/nokogiri/XsltStylesheet.java +126 -0
  38. data/ext/java/nokogiri/internals/HtmlDomParserContext.java +181 -0
  39. data/ext/java/nokogiri/internals/NokogiriDocumentCache.java +39 -0
  40. data/ext/java/nokogiri/internals/NokogiriErrorHandler.java +42 -0
  41. data/ext/java/nokogiri/internals/NokogiriHandler.java +251 -0
  42. data/ext/java/nokogiri/internals/NokogiriHelpers.java +526 -0
  43. data/ext/java/nokogiri/internals/NokogiriNamespaceCache.java +136 -0
  44. data/ext/java/nokogiri/internals/NokogiriNamespaceContext.java +80 -0
  45. data/ext/java/nokogiri/internals/NokogiriNonStrictErrorHandler.java +37 -0
  46. data/ext/java/nokogiri/internals/NokogiriNonStrictErrorHandler4NekoHtml.java +54 -0
  47. data/ext/java/nokogiri/internals/NokogiriStrictErrorHandler.java +49 -0
  48. data/ext/java/nokogiri/internals/NokogiriXPathFunction.java +88 -0
  49. data/ext/java/nokogiri/internals/NokogiriXPathFunctionResolver.java +23 -0
  50. data/ext/java/nokogiri/internals/ParserContext.java +235 -0
  51. data/ext/java/nokogiri/internals/PushInputStream.java +381 -0
  52. data/ext/java/nokogiri/internals/ReaderNode.java +431 -0
  53. data/ext/java/nokogiri/internals/SaveContext.java +249 -0
  54. data/ext/java/nokogiri/internals/SchemaErrorHandler.java +35 -0
  55. data/ext/java/nokogiri/internals/XmlDeclHandler.java +10 -0
  56. data/ext/java/nokogiri/internals/XmlDomParser.java +45 -0
  57. data/ext/java/nokogiri/internals/XmlDomParserContext.java +201 -0
  58. data/ext/java/nokogiri/internals/XmlSaxParser.java +33 -0
  59. data/ext/nokogiri/depend +32 -0
  60. data/ext/nokogiri/extconf.rb +61 -32
  61. data/ext/nokogiri/libcharset-1.dll +0 -0
  62. data/ext/nokogiri/libexslt.dll +0 -0
  63. data/ext/nokogiri/libiconv-2.dll +0 -0
  64. data/ext/nokogiri/libxml2.dll +0 -0
  65. data/ext/nokogiri/libxslt.dll +0 -0
  66. data/ext/nokogiri/nokogiri.c +0 -5
  67. data/ext/nokogiri/nokogiri.h +2 -2
  68. data/ext/nokogiri/xml_document.c +5 -0
  69. data/ext/nokogiri/xml_libxml2_hacks.c +112 -0
  70. data/ext/nokogiri/xml_libxml2_hacks.h +12 -0
  71. data/ext/nokogiri/xml_node.c +56 -16
  72. data/ext/nokogiri/xml_node_set.c +7 -7
  73. data/ext/nokogiri/xml_reader.c +20 -1
  74. data/ext/nokogiri/xml_relax_ng.c +0 -7
  75. data/ext/nokogiri/xml_xpath_context.c +2 -0
  76. data/ext/nokogiri/zlib1.dll +0 -0
  77. data/lib/nokogiri.rb +1 -2
  78. data/lib/nokogiri/css/generated_parser.rb +155 -148
  79. data/lib/nokogiri/css/generated_tokenizer.rb +2 -1
  80. data/lib/nokogiri/css/parser.y +3 -0
  81. data/lib/nokogiri/css/xpath_visitor.rb +1 -7
  82. data/lib/nokogiri/html.rb +2 -2
  83. data/lib/nokogiri/html/document_fragment.rb +7 -4
  84. data/lib/nokogiri/nokogiri.jar +0 -0
  85. data/lib/nokogiri/version.rb +3 -6
  86. data/lib/nokogiri/xml/builder.rb +1 -1
  87. data/lib/nokogiri/xml/document.rb +1 -2
  88. data/lib/nokogiri/xml/document_fragment.rb +7 -0
  89. data/lib/nokogiri/xml/node.rb +5 -3
  90. data/lib/nokogiri/xml/node_set.rb +25 -0
  91. data/lib/nokogiri/xml/reader.rb +2 -0
  92. data/lib/nokogiri/xml/sax/document.rb +3 -1
  93. data/spec/helper.rb +3 -0
  94. data/spec/xml/reader_spec.rb +307 -0
  95. data/tasks/test.rb +1 -1
  96. data/test/css/test_parser.rb +11 -1
  97. data/test/html/sax/test_parser_context.rb +2 -2
  98. data/test/html/test_document.rb +2 -2
  99. data/test/html/test_document_fragment.rb +34 -6
  100. data/test/test_memory_leak.rb +2 -2
  101. data/test/test_reader.rb +28 -6
  102. data/test/test_xslt_transforms.rb +2 -3
  103. data/test/xml/test_attr.rb +31 -4
  104. data/test/xml/test_builder.rb +5 -5
  105. data/test/xml/test_cdata.rb +3 -3
  106. data/test/xml/test_document.rb +8 -8
  107. data/test/xml/test_document_fragment.rb +4 -12
  108. data/test/xml/test_node.rb +1 -1
  109. data/test/xml/test_node_reparenting.rb +26 -11
  110. data/test/xml/test_node_set.rb +38 -2
  111. data/test/xml/test_text.rb +11 -2
  112. data/test/xml/test_unparented_node.rb +1 -1
  113. data/test/xml/test_xpath.rb +11 -7
  114. metadata +159 -100
  115. data.tar.gz.sig +0 -0
  116. data/lib/nokogiri/version_warning.rb +0 -14
  117. metadata.gz.sig +0 -0
@@ -0,0 +1,146 @@
1
+ package nokogiri;
2
+
3
+ import static nokogiri.internals.NokogiriHelpers.getNokogiriClass;
4
+ import static org.jruby.javasupport.util.RuntimeHelpers.invoke;
5
+
6
+ import java.io.IOException;
7
+ import java.io.InputStream;
8
+ import java.nio.channels.ClosedChannelException;
9
+
10
+ import nokogiri.internals.ParserContext;
11
+ import nokogiri.internals.PushInputStream;
12
+
13
+ import org.jruby.Ruby;
14
+ import org.jruby.RubyClass;
15
+ import org.jruby.RubyException;
16
+ import org.jruby.RubyObject;
17
+ import org.jruby.RubyString;
18
+ import org.jruby.anno.JRubyClass;
19
+ import org.jruby.anno.JRubyMethod;
20
+ import org.jruby.exceptions.RaiseException;
21
+ import org.jruby.runtime.ThreadContext;
22
+ import org.jruby.runtime.builtin.IRubyObject;
23
+
24
+ @JRubyClass(name="Nokogiri::XML::SAX::PushParser")
25
+ public class XmlSaxPushParser extends RubyObject {
26
+ ParserContext.Options options;
27
+ IRubyObject optionsRuby;
28
+ PushInputStream stream;
29
+ Thread reader;
30
+ Runner runner;
31
+
32
+ public XmlSaxPushParser(Ruby ruby, RubyClass rubyClass) {
33
+ super(ruby, rubyClass);
34
+ }
35
+
36
+ @JRubyMethod
37
+ public IRubyObject initialize_native(final ThreadContext context,
38
+ IRubyObject _saxParser,
39
+ IRubyObject fileName) {
40
+ optionsRuby = invoke(context,
41
+ context.getRuntime().getClassFromPath("Nokogiri::XML::ParseOptions"),
42
+ "new");
43
+ options = new ParserContext.Options(0);
44
+ stream = new PushInputStream();
45
+
46
+ runner = new Runner(context, this, stream);
47
+ reader = new Thread(runner);
48
+ reader.start();
49
+
50
+ return this;
51
+ }
52
+
53
+ /**
54
+ * Returns an integer.
55
+ */
56
+ @JRubyMethod(name="options")
57
+ public IRubyObject getOptions(ThreadContext context) {
58
+ return invoke(context, optionsRuby, "options");
59
+ }
60
+
61
+ /**
62
+ * <code>val</code> is an integer.
63
+ */
64
+ @JRubyMethod(name="options=")
65
+ public IRubyObject setOptions(ThreadContext context, IRubyObject val) {
66
+ invoke(context, optionsRuby, "options=", val);
67
+ options =
68
+ new ParserContext.Options(val.convertToInteger().getLongValue());
69
+ return getOptions(context);
70
+ }
71
+
72
+ @JRubyMethod
73
+ public IRubyObject native_write(ThreadContext context, IRubyObject chunk,
74
+ IRubyObject isLast) {
75
+ byte[] data = null;
76
+ if (chunk instanceof RubyString || chunk.respondsTo("to_str")) {
77
+ data = chunk.convertToString().getBytes();
78
+ } else {
79
+ throw new RaiseException(new XmlSyntaxError(context.getRuntime()));
80
+ }
81
+
82
+ int errorCount0 = runner.getErrorCount();
83
+
84
+ try {
85
+ stream.writeAndWaitForRead(data);
86
+ } catch (ClosedChannelException e) {
87
+ // ignore
88
+ } catch (IOException e) {
89
+ throw context.getRuntime().newRuntimeError(e.toString());
90
+ }
91
+
92
+ if (isLast.isTrue()) {
93
+ try {
94
+ stream.close();
95
+ } catch (IOException e) {
96
+ // ignore
97
+ }
98
+
99
+ for (;;) {
100
+ try {
101
+ reader.join();
102
+ break;
103
+ } catch (InterruptedException e) {
104
+ // continue loop
105
+ }
106
+ }
107
+ }
108
+
109
+ if (!options.recover && runner.getErrorCount() > errorCount0) {
110
+ throw new RaiseException(runner.getLastError(), true);
111
+ }
112
+
113
+ return this;
114
+ }
115
+
116
+ protected static class Runner implements Runnable {
117
+ protected ThreadContext context;
118
+ protected IRubyObject handler;
119
+ protected XmlSaxParserContext parser;
120
+
121
+ public Runner(ThreadContext context,
122
+ IRubyObject handler,
123
+ InputStream stream) {
124
+ RubyClass klazz = getNokogiriClass(context.getRuntime(), "Nokogiri::XML::SAX::ParserContext");
125
+
126
+ this.context = context;
127
+ this.handler = handler;
128
+ this.parser = (XmlSaxParserContext)
129
+ XmlSaxParserContext.parse_stream(context, klazz, stream);
130
+ }
131
+
132
+ public void run() {
133
+ parser.parse_with(context, handler);
134
+ }
135
+
136
+ public int getErrorCount() {
137
+ // check for null because thread may nto have started yet
138
+ if (parser.getNokogiriHandler() == null) return 0;
139
+ else return parser.getNokogiriHandler().getErrorCount();
140
+ }
141
+
142
+ public RubyException getLastError() {
143
+ return (RubyException) parser.getNokogiriHandler().getLastError();
144
+ }
145
+ }
146
+ }
@@ -0,0 +1,142 @@
1
+ package nokogiri;
2
+
3
+ import static nokogiri.internals.NokogiriHelpers.getNokogiriClass;
4
+
5
+ import java.io.IOException;
6
+ import java.io.StringReader;
7
+
8
+ import javax.xml.XMLConstants;
9
+ import javax.xml.transform.Source;
10
+ import javax.xml.transform.dom.DOMSource;
11
+ import javax.xml.transform.stream.StreamSource;
12
+ import javax.xml.validation.Schema;
13
+ import javax.xml.validation.SchemaFactory;
14
+ import javax.xml.validation.Validator;
15
+
16
+ import nokogiri.internals.SchemaErrorHandler;
17
+ import nokogiri.internals.XmlDomParserContext;
18
+
19
+ import org.jruby.Ruby;
20
+ import org.jruby.RubyArray;
21
+ import org.jruby.RubyClass;
22
+ import org.jruby.RubyFixnum;
23
+ import org.jruby.RubyObject;
24
+ import org.jruby.anno.JRubyClass;
25
+ import org.jruby.anno.JRubyMethod;
26
+ import org.jruby.exceptions.RaiseException;
27
+ import org.jruby.runtime.ThreadContext;
28
+ import org.jruby.runtime.Visibility;
29
+ import org.jruby.runtime.builtin.IRubyObject;
30
+ import org.w3c.dom.Document;
31
+ import org.xml.sax.ErrorHandler;
32
+ import org.xml.sax.SAXException;
33
+
34
+ /**
35
+ *
36
+ * @author sergio
37
+ */
38
+ @JRubyClass(name="Nokogiri::XML::Schema")
39
+ public class XmlSchema extends RubyObject {
40
+
41
+ protected Source source;
42
+
43
+ public XmlSchema(Ruby ruby, RubyClass klazz) {
44
+ super(ruby, klazz);
45
+ }
46
+
47
+ private Schema getSchema(ThreadContext context) {
48
+
49
+ Schema schema = null;
50
+
51
+ String uri=XMLConstants.W3C_XML_SCHEMA_NS_URI;
52
+
53
+ try {
54
+ schema = SchemaFactory.newInstance(uri).newSchema(source);
55
+ } catch(SAXException ex) {
56
+ throw context.getRuntime().newRuntimeError("Could not parse document: "+ex.getMessage());
57
+ }
58
+ return schema;
59
+ }
60
+
61
+ protected static XmlSchema createSchemaWithSource(ThreadContext context, RubyClass klazz, Source source) {
62
+ Ruby ruby = context.getRuntime();
63
+ XmlSchema schema = null;
64
+ if( klazz.ancestors(context).include_p(context,
65
+ getNokogiriClass(ruby, "Nokogiri::XML::RelaxNG")).isTrue()) {
66
+ schema = new XmlRelaxng(ruby, klazz);
67
+ } else {
68
+ schema = new XmlSchema(ruby, klazz);
69
+ }
70
+ schema.source = source;
71
+
72
+ schema.setInstanceVariable("@errors", ruby.newEmptyArray());
73
+ return schema;
74
+ }
75
+
76
+ @JRubyMethod(meta=true)
77
+ public static IRubyObject from_document(ThreadContext context, IRubyObject klazz, IRubyObject document) {
78
+ XmlDocument doc = ((XmlDocument) ((XmlNode) document).document(context));
79
+
80
+ RubyArray errors = (RubyArray) doc.getInstanceVariable("@errors");
81
+
82
+ if(!errors.isEmpty()) {
83
+ throw new RaiseException((XmlSyntaxError) errors.first());
84
+ }
85
+
86
+ DOMSource source = new DOMSource(doc.getDocument());
87
+
88
+ IRubyObject uri = doc.url(context);
89
+
90
+ if(!uri.isNil()) {
91
+ source.setSystemId(uri.convertToString().asJavaString());
92
+ }
93
+
94
+ return createSchemaWithSource(context, (RubyClass) klazz, source);
95
+ }
96
+
97
+ @JRubyMethod(meta=true)
98
+ public static IRubyObject read_memory(ThreadContext context, IRubyObject klazz, IRubyObject content) {
99
+
100
+ String data = content.convertToString().asJavaString();
101
+
102
+ return createSchemaWithSource(context, (RubyClass) klazz,
103
+ new StreamSource(new StringReader(data)));
104
+ }
105
+
106
+ @JRubyMethod(visibility=Visibility.PRIVATE)
107
+ public IRubyObject validate_document(ThreadContext context, IRubyObject document) {
108
+ return validate_document_or_file(context, (XmlDocument)document);
109
+ }
110
+
111
+ @JRubyMethod(visibility=Visibility.PRIVATE)
112
+ public IRubyObject validate_file(ThreadContext context, IRubyObject file) {
113
+ Ruby ruby = context.getRuntime();
114
+
115
+ XmlDomParserContext ctx = new XmlDomParserContext(ruby, RubyFixnum.newFixnum(ruby, 1L));
116
+ ctx.setInputSource(context, file);
117
+ XmlDocument xmlDocument = ctx.parse(context, getNokogiriClass(ruby, "Nokogiri::XML::Document"), ruby.getNil());
118
+ return validate_document_or_file(context, xmlDocument);
119
+ }
120
+
121
+ private IRubyObject validate_document_or_file(ThreadContext context, XmlDocument xmlDocument) {
122
+ Document doc = xmlDocument.getDocument();
123
+
124
+ DOMSource docSource = new DOMSource(doc);
125
+ Validator validator = getSchema(context).newValidator();
126
+
127
+ RubyArray errors = (RubyArray) this.getInstanceVariable("@errors");
128
+ ErrorHandler errorHandler = new SchemaErrorHandler(context.getRuntime(), errors);
129
+
130
+ validator.setErrorHandler(errorHandler);
131
+
132
+ try {
133
+ validator.validate(docSource);
134
+ } catch(SAXException ex) {
135
+ errors.append(new XmlSyntaxError(context.getRuntime(), ex));
136
+ } catch (IOException ex) {
137
+ throw context.getRuntime().newIOError(ex.getMessage());
138
+ }
139
+
140
+ return errors;
141
+ }
142
+ }
@@ -0,0 +1,84 @@
1
+ package nokogiri;
2
+
3
+ import static nokogiri.internals.NokogiriHelpers.stringOrNil;
4
+
5
+ import org.jruby.Ruby;
6
+ import org.jruby.RubyClass;
7
+ import org.jruby.RubyException;
8
+ import org.jruby.RubyModule;
9
+ import org.jruby.anno.JRubyClass;
10
+ import org.xml.sax.SAXParseException;
11
+
12
+ @JRubyClass(name="Nokogiri::XML::SyntaxError", parent="Nokogiri::SyntaxError")
13
+ public class XmlSyntaxError extends RubyException {
14
+
15
+ protected Exception exception;
16
+
17
+ public static RubyClass getRubyClass(Ruby ruby) {
18
+ return ((RubyModule) ruby.getModule("Nokogiri").getConstant("XML")).getClass("SyntaxError");
19
+ }
20
+
21
+ public XmlSyntaxError(Ruby ruby){
22
+ this(ruby, getRubyClass(ruby));
23
+ }
24
+
25
+ public XmlSyntaxError(Ruby ruby, RubyClass rubyClass) {
26
+ super(ruby, rubyClass);
27
+ }
28
+
29
+ public XmlSyntaxError(Ruby ruby, Exception ex) {
30
+ this(ruby);
31
+ this.exception = ex;
32
+ }
33
+
34
+ public XmlSyntaxError(Ruby ruby, RubyClass rubyClass, Exception ex) {
35
+ super(ruby, rubyClass, ex.getMessage());
36
+ this.exception = ex;
37
+ }
38
+
39
+ public static XmlSyntaxError createWarning(Ruby ruby, SAXParseException e) {
40
+ return new XmlSyntaxError(ruby, e, 1);
41
+ }
42
+
43
+ public static XmlSyntaxError createError(Ruby ruby, SAXParseException e) {
44
+ return new XmlSyntaxError(ruby, e, 2);
45
+ }
46
+
47
+ public static XmlSyntaxError createFatalError(Ruby ruby, SAXParseException e) {
48
+ return new XmlSyntaxError(ruby, e, 3);
49
+ }
50
+
51
+ public XmlSyntaxError(Ruby ruby, SAXParseException e, int level) {
52
+ super(ruby, getRubyClass(ruby), e.getMessage());
53
+ this.exception = e;
54
+ setInstanceVariable("@level", ruby.newFixnum(level));
55
+ setInstanceVariable("@line", ruby.newFixnum(e.getLineNumber()));
56
+ setInstanceVariable("@column", ruby.newFixnum(e.getColumnNumber()));
57
+ setInstanceVariable("@file", stringOrNil(ruby, e.getSystemId()));
58
+ }
59
+
60
+ public static RubyException createXPathSyntaxError(Ruby runtime, Exception e) {
61
+ RubyClass klazz = (RubyClass)
62
+ runtime.getClassFromPath("Nokogiri::XML::XPath::SyntaxError");
63
+ return new XmlSyntaxError(runtime, klazz, e);
64
+ }
65
+
66
+ // public static RubyException getXPathSyntaxError(ThreadContext context, Exception ex) {
67
+ // Ruby ruby = context.getRuntime();
68
+ // RubyClass klazz = (RubyClass) ruby.getClassFromPath("Nokogiri::XML::XPath::SyntaxError");
69
+ // return new XmlSyntaxError(ruby, klazz, ex);
70
+ // }
71
+
72
+ //TODO: Return correct message, domain, etc.
73
+
74
+ // @JRubyMethod
75
+ // @Override
76
+ // public IRubyObject message(ThreadContext context) {
77
+ // if(this.exception != null) {
78
+ // return context.getRuntime().newString(this.exception.toString());
79
+ // } else {
80
+ // return context.getRuntime().newString("no message");
81
+ // }
82
+ // }
83
+
84
+ }
@@ -0,0 +1,96 @@
1
+ package nokogiri;
2
+
3
+ import static nokogiri.internals.NokogiriHelpers.isXmlEscaped;
4
+ import static nokogiri.internals.NokogiriHelpers.stringOrNil;
5
+ import nokogiri.internals.NokogiriHelpers;
6
+ import nokogiri.internals.SaveContext;
7
+
8
+ import org.jruby.Ruby;
9
+ import org.jruby.RubyClass;
10
+ import org.jruby.anno.JRubyClass;
11
+ import org.jruby.anno.JRubyMethod;
12
+ import org.jruby.javasupport.JavaUtil;
13
+ import org.jruby.runtime.ThreadContext;
14
+ import org.jruby.runtime.builtin.IRubyObject;
15
+ import org.w3c.dom.Document;
16
+ import org.w3c.dom.Node;
17
+
18
+ @JRubyClass(name="Nokogiri::XML::Text", parent="Nokogiri::XML::CharacterData")
19
+ public class XmlText extends XmlNode {
20
+ public XmlText(Ruby ruby, RubyClass rubyClass, Node node) {
21
+ super(ruby, rubyClass, node);
22
+ }
23
+
24
+ public XmlText(Ruby runtime, RubyClass klass) {
25
+ super(runtime, klass);
26
+ }
27
+
28
+ @Override
29
+ protected void init(ThreadContext context, IRubyObject[] args) {
30
+ if (args.length < 2) {
31
+ throw getRuntime().newArgumentError(args.length, 2);
32
+ }
33
+
34
+ content = args[0];
35
+ IRubyObject xNode = args[1];
36
+
37
+ XmlNode xmlNode = asXmlNode(context, xNode);
38
+ XmlDocument xmlDoc = (XmlDocument)xmlNode.document(context);
39
+ doc = xmlDoc;
40
+ Document document = xmlDoc.getDocument();
41
+ // text node content should not be encoded when it is created by Text node.
42
+ // while content should be encoded when it is created by Element node.
43
+ Node node = document.createTextNode((String)content.toJava(String.class));
44
+ setNode(node);
45
+ }
46
+
47
+ @Override
48
+ protected IRubyObject getNodeName(ThreadContext context) {
49
+ return JavaUtil.convertJavaToUsableRubyObject(context.getRuntime(), "text");
50
+ }
51
+
52
+ @Override
53
+ @JRubyMethod(name = {"content", "text", "inner_text"})
54
+ public IRubyObject content(ThreadContext context) {
55
+ if (content == null || content.isNil()) {
56
+ return stringOrNil(context.getRuntime(), node.getTextContent());
57
+ } else {
58
+ return content;
59
+ }
60
+ }
61
+
62
+ @Override
63
+ public void saveContent(ThreadContext context, SaveContext ctx) {
64
+ String textContent = node.getTextContent();
65
+
66
+ if (!isXmlEscaped(textContent)) {
67
+ textContent = NokogiriHelpers.encodeJavaString(textContent);
68
+ }
69
+ if (getEncoding(context, ctx) == null) {
70
+ textContent = encodeStringToHtmlEntity(textContent);
71
+ }
72
+ ctx.append(textContent);
73
+ }
74
+
75
+ private String getEncoding(ThreadContext context, SaveContext ctx) {
76
+ String encoding = ctx.getEncoding();
77
+ if (encoding != null) return encoding;
78
+ XmlDocument xmlDocument = (XmlDocument)document(context);
79
+ IRubyObject ruby_encoding = xmlDocument.encoding(context);
80
+ if (!ruby_encoding.isNil()) {
81
+ encoding = (String)ruby_encoding.toJava(String.class);
82
+ }
83
+ return encoding;
84
+ }
85
+
86
+ private String encodeStringToHtmlEntity(String text) {
87
+ int last = 126; // = U+007E. No need to encode under U+007E.
88
+ StringBuffer sb = new StringBuffer();
89
+ for (int i=0; i<text.length(); i++) {
90
+ int codePoint = text.codePointAt(i);
91
+ if (codePoint > last) sb.append("&#x" + Integer.toHexString(codePoint) + ";");
92
+ else sb.append(text.charAt(i));
93
+ }
94
+ return new String(sb);
95
+ }
96
+ }