Skip to content

Commit

Permalink
refs shepmaster#50 dtd can have internal, external, both, or neither.
Browse files Browse the repository at this point in the history
  • Loading branch information
onelson committed Mar 12, 2018
1 parent 4dd7aea commit a830a28
Showing 1 changed file with 84 additions and 14 deletions.
98 changes: 84 additions & 14 deletions src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -484,6 +484,7 @@ fn parse_external_id<'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("SYSTEM"));
let (xml, _) = try_parse!(xml.expect_space());
let (xml, external_id) = try_parse!(
Expand All @@ -495,35 +496,30 @@ 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>)
fn parse_int_subset<'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, _) = xml.consume_space().optional(xml);
let (xml, _) = try_parse!(xml.expect_literal("]"));
let (xml, _) = xml.consume_space().optional(xml);

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("<!DOCTYPE"));
let (xml, _) = try_parse!(xml.expect_space());
let (xml, _type_name) = try_parse!(xml.consume_name().map_err(|_| SpecificError::ExpectedDocumentTypeName));


let (xml, _id) = try_parse!(
pm.alternate()
.one(|p| parse_external_id(p, xml))
.one(|p| parse_internal_dtd(p, xml))
.finish()
let (xml, _type_name) = try_parse!(
xml.consume_name().map_err(|_| SpecificError::ExpectedDocumentTypeName)
);

let (xml, _id) = try_parse!(pm.optional(xml, |p, x| parse_external_id(p, x)));
let (xml, _) = xml.consume_space().optional(xml);
let (xml, _int_subset) = try_parse!(pm.optional(xml, |p, x| parse_int_subset(p, x)));
let (xml, _) = try_parse!(xml.expect_literal(">"));

success(Token::DocumentTypeDeclaration, xml)
Expand Down Expand Up @@ -1340,7 +1336,7 @@ mod test {
}

#[test]
fn a_prolog_with_a_document_type_declaration() {
fn a_prolog_with_a_doc_type_declaration_external_id() {
let package = quick_parse("<?xml version='1.0'?>\
<!DOCTYPE doc SYSTEM \"http://example.com/doc.dtd\">\
<hello/>");
Expand All @@ -1351,7 +1347,7 @@ mod test {
}

#[test]
fn a_prolog_with_an_internal_document_type_declaration() {
fn a_prolog_with_a_doc_type_declaration_int_subset() {
let package = quick_parse(r#"<?xml version="1.0"?>
<!DOCTYPE note [
<!ELEMENT note (to,from,heading,body)>
Expand All @@ -1373,6 +1369,80 @@ mod test {
assert_qname_eq!(top.name(), "note");
}

#[test]
fn a_prolog_with_a_doc_type_declaration_int_subset_trailing_ws() {
let package = quick_parse(r#"<?xml version="1.0"?>
<!DOCTYPE note
[
<!ELEMENT note (to,from,heading,body)>
<!ELEMENT to (#PCDATA)>
<!ELEMENT from (#PCDATA)>
<!ELEMENT heading (#PCDATA)>
<!ELEMENT body (#PCDATA)>
]
>
<note>
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend</body>
</note>
"#);
let doc = package.as_document();
let top = top(&doc);

assert_qname_eq!(top.name(), "note");
}

#[test]
fn a_prolog_with_a_doc_type_declaration_zero_def() {
let package = quick_parse("<?xml version='1.0'?>\
<!DOCTYPE doc>\
<hello/>");
let doc = package.as_document();
let top = top(&doc);

assert_qname_eq!(top.name(), "hello");
}

#[test]
fn a_prolog_with_a_doc_type_declaration_zero_def_trailing_ws() {
let package = quick_parse("<?xml version='1.0'?>\
<!DOCTYPE doc >\
<hello/>");
let doc = package.as_document();
let top = top(&doc);

assert_qname_eq!(top.name(), "hello");
}

#[test]
fn a_prolog_with_a_doc_type_declaration_both_int_subset_and_external_id() {
let package = quick_parse("<?xml version='1.0'?>\
<!DOCTYPE doc SYSTEM \"http://example.com/doc.dtd\" [\
<!ELEMENT hello (#PCDATA)>
]>\
<hello/>");
let doc = package.as_document();
let top = top(&doc);

assert_qname_eq!(top.name(), "hello");
}

#[test]
fn a_prolog_with_a_doc_type_declaration_both_int_subset_and_external_id_trailing_ws() {
let package = quick_parse("<?xml version='1.0'?>\
<!DOCTYPE doc SYSTEM \"http://example.com/doc.dtd\" [\
<!ELEMENT hello (#PCDATA)>
] > \
<hello/>");
let doc = package.as_document();
let top = top(&doc);

assert_qname_eq!(top.name(), "hello");
}

#[test]
fn a_document_with_a_single_element() {
let package = quick_parse("<hello />");
Expand Down

0 comments on commit a830a28

Please sign in to comment.