aboutsummaryrefslogtreecommitdiffstats
path: root/src/xml/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/xml/mod.rs')
-rw-r--r--src/xml/mod.rs101
1 files changed, 94 insertions, 7 deletions
diff --git a/src/xml/mod.rs b/src/xml/mod.rs
index 2d20ca0..8fb5419 100644
--- a/src/xml/mod.rs
+++ b/src/xml/mod.rs
@@ -1,4 +1,6 @@
-use std::{char, ops::Deref};
+use std::{char, convert::Infallible, ops::Deref, str::FromStr};
+
+use parsers_complete::Parser;
use crate::error::Error;
@@ -228,14 +230,14 @@ pub enum EntityValue<'s> {
SingleQuoted(Vec<EntityValueData<'s>>),
}
-#[derive(Clone, Debug)]
+#[derive(Clone, Debug, PartialEq, Eq)]
pub enum AttValueData<'s> {
String(&'s str),
Reference(Reference<'s>),
}
/// [10] AttValue ::= '"' ([^<&"] | Reference)* '"'
/// | "'" ([^<&'] | Reference)* "'"
-#[derive(Clone, Debug)]
+#[derive(Clone, Debug, PartialEq, Eq)]
pub enum AttValue<'s> {
DoubleQuoted(Vec<AttValueData<'s>>),
SingleQuoted(Vec<AttValueData<'s>>),
@@ -259,6 +261,34 @@ impl<'s> AttValue<'s> {
}
}
+impl<'s> From<&'s str> for AttValue<'s> {
+ fn from(s: &'s str) -> AttValue<'s> {
+ let mut data = Vec::new();
+ for str in s.split_inclusive(|c| c == '<' || c == '"') {
+ if let Some(str) = str.strip_suffix('<') {
+ if !str.is_empty() {
+ data.push(AttValueData::String(str))
+ }
+ data.push(AttValueData::Reference(Reference::EntityRef(EntityRef(
+ Name::parse_full("lt").unwrap(),
+ ))))
+ } else if let Some(str) = str.strip_suffix('"') {
+ if !str.is_empty() {
+ data.push(AttValueData::String(str))
+ }
+ data.push(AttValueData::Reference(Reference::EntityRef(EntityRef(
+ Name::parse_full("quot").unwrap(),
+ ))))
+ } else {
+ if !str.is_empty() {
+ data.push(AttValueData::String(str))
+ }
+ }
+ }
+ AttValue::DoubleQuoted(data)
+ }
+}
+
/// [11] SystemLiteral ::= ('"' [^"]* '"') | ("'" [^']* "'")
#[derive(Debug)]
pub enum SystemLiteral<'s> {
@@ -673,7 +703,7 @@ pub struct IgnoreSectContents<'s> {
pub struct Ignore<'s>(&'s str);
/// [66] CharRef ::= '&#' [0-9]+ ';' | '&#x' [0-9a-fA-F]+ ';'
-#[derive(Clone, Debug)]
+#[derive(Clone, Debug, PartialEq, Eq)]
pub enum CharRef<'s> {
Decimal(&'s str),
Hexadecimal(&'s str),
@@ -706,7 +736,7 @@ impl<'s> CharRef<'s> {
}
/// [67] Reference ::= EntityRef | CharRef
-#[derive(Clone, Debug)]
+#[derive(Clone, Debug, PartialEq, Eq)]
pub enum Reference<'s> {
EntityRef(EntityRef<'s>),
CharRef(CharRef<'s>),
@@ -729,8 +759,8 @@ impl<'s> Reference<'s> {
}
/// [68] EntityRef ::= '&' Name ';'
-#[derive(Clone, Debug)]
-pub struct EntityRef<'s>(Name<'s>);
+#[derive(Clone, Debug, PartialEq, Eq)]
+pub struct EntityRef<'s>(pub(crate) Name<'s>);
impl<'s> Deref for EntityRef<'s> {
type Target = Name<'s>;
@@ -835,3 +865,60 @@ pub struct NotationDecl<'s> {
/// [83] PublicID ::= 'PUBLIC' S PubidLiteral
#[derive(Debug)]
pub struct PublicID<'s>(PubidLiteral<'s>);
+
+#[cfg(test)]
+mod test {
+ use super::{AttValue, AttValueData, EntityRef, Name, Reference};
+
+ #[test]
+ fn att_value_from_str() {
+ assert_eq!(
+ AttValue::from("hsdaflaskdf<laksdf<abdsf"),
+ AttValue::DoubleQuoted(vec![
+ AttValueData::String("hsdaflaskdf"),
+ AttValueData::Reference(Reference::EntityRef(EntityRef(Name("lt")))),
+ AttValueData::String("laksdf"),
+ AttValueData::Reference(Reference::EntityRef(EntityRef(Name("lt")))),
+ AttValueData::String("abdsf"),
+ ])
+ );
+ assert_eq!(
+ AttValue::from("hsdaflaskdf<laksdf\"abdsf"),
+ AttValue::DoubleQuoted(vec![
+ AttValueData::String("hsdaflaskdf"),
+ AttValueData::Reference(Reference::EntityRef(EntityRef(Name("lt")))),
+ AttValueData::String("laksdf"),
+ AttValueData::Reference(Reference::EntityRef(EntityRef(Name("quot")))),
+ AttValueData::String("abdsf"),
+ ])
+ );
+ assert_eq!(
+ AttValue::from("hsdaflaskdf<laksdf\""),
+ AttValue::DoubleQuoted(vec![
+ AttValueData::String("hsdaflaskdf"),
+ AttValueData::Reference(Reference::EntityRef(EntityRef(Name("lt")))),
+ AttValueData::String("laksdf"),
+ AttValueData::Reference(Reference::EntityRef(EntityRef(Name("quot")))),
+ ])
+ );
+ assert_eq!(
+ AttValue::from("hsdaflaskdf\"<<laksdf\""),
+ AttValue::DoubleQuoted(vec![
+ AttValueData::String("hsdaflaskdf"),
+ AttValueData::Reference(Reference::EntityRef(EntityRef(Name("quot")))),
+ AttValueData::Reference(Reference::EntityRef(EntityRef(Name("lt")))),
+ AttValueData::Reference(Reference::EntityRef(EntityRef(Name("lt")))),
+ AttValueData::String("laksdf"),
+ AttValueData::Reference(Reference::EntityRef(EntityRef(Name("quot")))),
+ ])
+ );
+ assert_eq!(
+ AttValue::from("<<\""),
+ AttValue::DoubleQuoted(vec![
+ AttValueData::Reference(Reference::EntityRef(EntityRef(Name("lt")))),
+ AttValueData::Reference(Reference::EntityRef(EntityRef(Name("lt")))),
+ AttValueData::Reference(Reference::EntityRef(EntityRef(Name("quot")))),
+ ])
+ );
+ }
+}