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())) + } }