escape text and attribute values

This commit is contained in:
Astro 2017-08-12 02:05:18 +02:00
parent 8b50dadb92
commit 052c46635a
2 changed files with 51 additions and 3 deletions

View file

@ -18,6 +18,22 @@ use std::slice;
use convert::{IntoElements, IntoAttributeValue, ElementEmitter};
/// Escape XML text
pub fn write_escaped<W: Write>(writer: &mut W, input: &str) -> Result<()> {
for c in input.chars() {
match c {
'&' => write!(writer, "&amp;")?,
'<' => write!(writer, "&lt;")?,
'>' => write!(writer, "&gt;")?,
'\'' => write!(writer, "&apos;")?,
'"' => write!(writer, "&quot;")?,
_ => write!(writer, "{}", c)?,
}
}
Ok(())
}
/// A node in an element tree.
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum Node {
@ -71,7 +87,7 @@ impl Node {
fn write_to_inner<W: Write>(&self, writer: &mut W, last_namespace: &mut Option<String>) -> Result<()>{
match *self {
Node::Element(ref elmt) => elmt.write_to_inner(writer, last_namespace)?,
Node::Text(ref s) => write!(writer, "{}", s)?,
Node::Text(ref s) => write_escaped(writer, s)?,
}
Ok(())
@ -323,13 +339,17 @@ impl Element {
if let Some(ref ns) = self.namespace {
if *last_namespace != self.namespace {
write!(writer, " xmlns=\"{}\"", ns)?;
write!(writer, " xmlns=\"")?;
write_escaped(writer, ns)?;
write!(writer, "\"")?;
*last_namespace = Some(ns.clone());
}
}
for (key, value) in &self.attributes {
write!(writer, " {}=\"{}\"", key, value)?;
write!(writer, " {}=\"", key)?;
write_escaped(writer, value)?;
write!(writer, "\"")?;
}
if self.children.is_empty() {

View file

@ -43,6 +43,34 @@ fn writer_works() {
assert_eq!(String::from_utf8(writer).unwrap(), TEST_STRING);
}
#[test]
fn writer_escapes_attributes() {
let root = Element::builder("root")
.attr("a", "\"Air\" quotes")
.build();
let mut writer = Vec::new();
{
root.write_to(&mut writer).unwrap();
}
assert_eq!(String::from_utf8(writer).unwrap(),
r#"<?xml version="1.0" encoding="utf-8"?><root a="&quot;Air&quot; quotes" />"#
);
}
#[test]
fn writer_escapes_text() {
let root = Element::builder("root")
.append("<3")
.build();
let mut writer = Vec::new();
{
root.write_to(&mut writer).unwrap();
}
assert_eq!(String::from_utf8(writer).unwrap(),
r#"<?xml version="1.0" encoding="utf-8"?><root>&lt;3</root>"#
);
}
#[test]
fn builder_works() {
let elem = Element::builder("a")