diff --git a/src/parser.rs b/src/parser.rs
index ded408b..1646829 100644
--- a/src/parser.rs
+++ b/src/parser.rs
@@ -37,7 +37,6 @@ enum SpecificError {
ExpectedAttributeValue,
ExpectedCData,
-
ExpectedCharacterData,
ExpectedComment,
@@ -58,6 +57,7 @@ enum SpecificError {
ExpectedWhitespace,
ExpectedDocumentTypeName,
+ ExpectedInternalDTD,
ExpectedSystemLiteral,
ExpectedClosingQuote(&'static str),
@@ -151,6 +151,7 @@ impl error::Error for SpecificError {
ExpectedYesNo => "expected yes or no",
ExpectedWhitespace => "expected whitespace",
ExpectedDocumentTypeName => "expected document type name",
+ ExpectedInternalDTD => "expected Internal DTD definition",
ExpectedSystemLiteral => "expected system literal",
ExpectedClosingQuote(_) => "expected closing quote",
ExpectedOpeningQuote(_) => "expected opening quote",
@@ -262,6 +263,7 @@ trait PrivateXmlParseExt<'a> {
fn consume_hex_chars(&self) -> XmlProgress<'a, &'a str>;
fn consume_char_data(&self) -> XmlProgress<'a, &'a str>;
fn consume_cdata(&self) -> XmlProgress<'a, &'a str>;
+ fn consume_internal_dtd(&self) -> XmlProgress<'a, &'a str>;
fn consume_comment(&self) -> XmlProgress<'a, &'a str>;
fn consume_pi_value(&self) -> XmlProgress<'a, &'a str>;
fn consume_start_tag(&self) -> XmlProgress<'a, &'a str>;
@@ -289,6 +291,10 @@ impl<'a> PrivateXmlParseExt<'a> for StringPoint<'a> {
self.consume_to(self.s.end_of_cdata()).map_err(|_| SpecificError::ExpectedCData)
}
+ fn consume_internal_dtd(&self) -> XmlProgress<'a, &'a str> {
+ self.consume_to(self.s.end_of_internal_dtd()).map_err(|_| SpecificError::ExpectedInternalDTD)
+ }
+
fn consume_comment(&self) -> XmlProgress<'a, &'a str> {
self.consume_to(self.s.end_of_comment()).map_err(|_| SpecificError::ExpectedCommentBody)
}
@@ -489,12 +495,34 @@ fn parse_external_id<'a>(pm: &mut XmlMaster<'a>, xml: StringPoint<'a>)
success(external_id, xml)
}
+fn parse_internal_dtd<'a>(_pm: &mut XmlMaster<'a>, xml: StringPoint<'a>)
+ -> XmlProgress<'a, &'a str>
+{
+ let (xml, _) = try_parse!(xml.expect_space());
+ let (xml, _) = try_parse!(xml.expect_literal("["));
+ let (xml, _) = xml.consume_space().optional(xml);
+ let (xml, elements) = try_parse!(
+ xml.consume_internal_dtd().map_err(|_| SpecificError::ExpectedInternalDTD)
+ );
+ let (xml, _) = try_parse!(xml.expect_literal("]"));
+
+ success(elements, xml)
+}
+
/* without the optional intSubset */
fn parse_document_type_declaration<'a>(pm: &mut XmlMaster<'a>, xml: StringPoint<'a>) -> XmlProgress<'a, Token<'a>> {
let (xml, _) = try_parse!(xml.expect_literal(""));
@@ -1322,6 +1350,29 @@ mod test {
assert_qname_eq!(top.name(), "hello");
}
+ #[test]
+ fn a_prolog_with_an_internal_document_type_declaration() {
+ let package = quick_parse(r#"
+
+
+
+
+
+ ]>
+
+ Tove
+ Jani
+ Reminder
+ Don't forget me this weekend
+
+ "#);
+ let doc = package.as_document();
+ let top = top(&doc);
+
+ assert_qname_eq!(top.name(), "note");
+ }
+
#[test]
fn a_document_with_a_single_element() {
let package = quick_parse("");
diff --git a/src/str.rs b/src/str.rs
index cd6fa71..2e7809a 100644
--- a/src/str.rs
+++ b/src/str.rs
@@ -49,6 +49,8 @@ pub trait XmlStr {
/// Find the end of the starting tag
fn end_of_start_tag(&self) -> Option;
fn end_of_encoding(&self) -> Option;
+ /// Find the end of the internal doc type declaration, not including the ]
+ fn end_of_internal_dtd(&self) -> Option;
}
impl<'a> XmlStr for &'a str {
@@ -143,6 +145,8 @@ impl<'a> XmlStr for &'a str {
fn end_of_encoding(&self) -> Option {
self.end_of_start_rest(|c| c.is_encoding_start_char(), |c| c.is_encoding_rest_char())
}
+
+ fn end_of_internal_dtd(&self) -> Option { self.find("]") }
}
/// Predicates used when parsing an characters in an XML document.
@@ -297,4 +301,9 @@ mod test {
fn end_of_char_data_includes_multiple_right_squares() {
assert_eq!("hello]]world".end_of_char_data(), Some("hello]]world".len()));
}
+
+ #[test]
+ fn end_of_internal_dtd_excludes_right_square() {
+ assert_eq!("hello]>world".end_of_internal_dtd(), Some("hello".len()))
+ }
}