Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Comparing changes

Choose two branches to see what's changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
base fork: adhearsion/nokogiri
...
head fork: adhearsion/nokogiri
Checking mergeability… Don't worry, you can still create the pull request.
  • 7 commits
  • 9 files changed
  • 0 commit comments
  • 1 contributor
View
4 ext/nokogiri/xml_document.c
@@ -198,9 +198,7 @@ static VALUE read_memory( VALUE klass,
xmlErrorPtr error = xmlGetLastError();
if(error)
- rb_funcall(rb_mKernel, rb_intern("raise"), 1,
- Nokogiri_wrap_xml_syntax_error((VALUE)NULL, error)
- );
+ Nokogiri_error_raise(NULL, error);
else
rb_raise(rb_eRuntimeError, "Could not parse document");
View
34 ext/nokogiri/xml_dtd.c
@@ -27,6 +27,34 @@ static void element_copier(void *_payload, void *data, xmlChar *name)
/*
* call-seq:
+ * parse_io(input, encoding)
+ *
+ * Load and parse a DTD using +input+ and +encoding+. Don't use this,
+ * you should probably use Nokogiri::XML::DTD.parse instead.
+ */
+static VALUE parse_io(VALUE klass, VALUE input_io, VALUE encoding)
+{
+
+ xmlParserInputBufferPtr input = xmlParserInputBufferCreateIO(
+ io_read_callback,
+ io_close_callback,
+ (void *)input_io,
+ NUM2INT(encoding)
+ );
+
+ xmlSetStructuredErrorFunc(NULL, Nokogiri_error_raise);
+ xmlDtdPtr dtd = xmlIOParseDTD(NULL, input, NUM2INT(encoding));
+ xmlSetStructuredErrorFunc(NULL, NULL);
+
+ if(!dtd) return Qnil;
+
+ /* This is not attached to a document, so we need to do memory cleanup
+ * ourselves. */
+ return Data_Wrap_Struct(cNokogiriXmlDtd, NULL, xmlFreeDtd, dtd);
+}
+
+/*
+ * call-seq:
* entities
*
* Get a hash of the elements for this DTD.
@@ -113,6 +141,8 @@ static VALUE validate(VALUE self, VALUE document)
return error_list;
}
+VALUE cNokogiriXmlDtd;
+
void init_xml_dtd()
{
VALUE nokogiri = rb_define_module("Nokogiri");
@@ -124,8 +154,12 @@ void init_xml_dtd()
*/
VALUE klass = rb_define_class_under(xml, "DTD", node);
+ cNokogiriXmlDtd = klass;
+
rb_define_method(klass, "notations", notations, 0);
rb_define_method(klass, "elements", elements, 0);
rb_define_method(klass, "entities", entities, 0);
rb_define_method(klass, "validate", validate, 1);
+
+ rb_define_singleton_method(klass, "parse_io", parse_io, 2);
}
View
2  ext/nokogiri/xml_dtd.h
@@ -5,4 +5,6 @@
void init_xml_dtd();
+extern VALUE cNokogiriXmlDtd;
+
#endif
View
2  ext/nokogiri/xml_node.c
@@ -845,7 +845,7 @@ VALUE Nokogiri_wrap_xml_node(VALUE klass, xmlNodePtr node)
klass = cNokogiriXmlCData;
break;
case XML_DTD_NODE:
- klass = rb_const_get(mNokogiriXml, rb_intern("DTD"));
+ klass = cNokogiriXmlDtd;
break;
default:
klass = cNokogiriXmlNode;
View
6 ext/nokogiri/xml_syntax_error.c
@@ -166,6 +166,12 @@ void Nokogiri_error_array_pusher(void * ctx, xmlErrorPtr error)
rb_ary_push(list, Nokogiri_wrap_xml_syntax_error((VALUE)NULL, error));
}
+void Nokogiri_error_raise(void * ctx, xmlErrorPtr error)
+{
+ rb_funcall(rb_mKernel, rb_intern("raise"), 1,
+ Nokogiri_wrap_xml_syntax_error((VALUE)NULL, error));
+}
+
VALUE Nokogiri_wrap_xml_syntax_error(VALUE klass, xmlErrorPtr error)
{
if(!klass) klass = cNokogiriXmlSyntaxError;
View
1  ext/nokogiri/xml_syntax_error.h
@@ -6,6 +6,7 @@
void init_xml_syntax_error();
VALUE Nokogiri_wrap_xml_syntax_error(VALUE klass, xmlErrorPtr error);
void Nokogiri_error_array_pusher(void * ctx, xmlErrorPtr error);
+void Nokogiri_error_raise(void * ctx, xmlErrorPtr error);
extern VALUE cNokogiriXmlSyntaxError;
#endif
View
16 lib/nokogiri/xml/dtd.rb
@@ -1,7 +1,23 @@
module Nokogiri
module XML
+ ###
+ # Parse the DTD contained in io_or_string
+ def self.DTD io_or_string
+ DTD.parse io_or_string
+ end
+
class DTD < Nokogiri::XML::Node
###
+ # Parse the DTD contained in io_or_string
+ def self.parse io_or_string
+ if [:read, :close].all? { |m| io_or_string.respond_to? m }
+ parse_io(io_or_string, 0)
+ else
+ parse_io(StringIO.new(io_or_string), 0)
+ end
+ end
+
+ ###
# Return attributes for DTD. Always returns +nil+
def attributes
nil
View
16 test/files/article.dtd
@@ -0,0 +1,16 @@
+<!ELEMENT NEWSPAPER (ARTICLE+)>
+<!ELEMENT ARTICLE (HEADLINE,BYLINE,LEAD,BODY,NOTES)>
+<!ELEMENT HEADLINE (#PCDATA)>
+<!ELEMENT BYLINE (#PCDATA)>
+<!ELEMENT LEAD (#PCDATA)>
+<!ELEMENT BODY (#PCDATA)>
+<!ELEMENT NOTES (#PCDATA)>
+
+<!ATTLIST ARTICLE AUTHOR CDATA #REQUIRED>
+<!ATTLIST ARTICLE EDITOR CDATA #IMPLIED>
+<!ATTLIST ARTICLE DATE CDATA #IMPLIED>
+<!ATTLIST ARTICLE EDITION CDATA #IMPLIED>
+
+<!ENTITY NEWSPAPER "Vervet Logic Times">
+<!ENTITY PUBLISHER "Vervet Logic Press">
+<!ENTITY COPYRIGHT "Copyright 1998 Vervet Logic Press">
View
30 test/xml/test_dtd.rb
@@ -14,6 +14,36 @@ def test_validate
assert_equal 44, list.length
end
+ def test_parse_invalid_dtd
+ assert_raises Nokogiri::XML::SyntaxError do
+ Nokogiri::XML::DTD.parse('asdfasdf')
+ end
+ end
+
+ def test_parse
+ dtd = nil
+ Dir.chdir(ASSETS_DIR) do
+ dtd = Nokogiri::XML::DTD.parse(File.open('article.dtd', 'rb'))
+ end
+ assert_equal 'none', dtd.name
+ end
+
+ def test_parse_string
+ dtd = nil
+ Dir.chdir(ASSETS_DIR) do
+ dtd = Nokogiri::XML::DTD.parse(File.read('article.dtd'))
+ end
+ assert_equal 'none', dtd.name
+ end
+
+ def test_parse_class_method
+ dtd = nil
+ Dir.chdir(ASSETS_DIR) do
+ dtd = Nokogiri::XML.DTD(File.read('article.dtd'))
+ end
+ assert_equal 'none', dtd.name
+ end
+
def test_external_subsets
assert subset = @xml.internal_subset
assert_equal 'staff', subset.name

No commit comments for this range

Something went wrong with that request. Please try again.