Skip to content

Make attribute creation more uniform #413

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
- [#395]: Add support for XML Schema `xs:list`
- [#324]: `Reader::from_str` / `Deserializer::from_str` / `from_str` now ignore
the XML declared encoding and always use UTF-8
- [#413]: Added `Attribute::from_bytes()`, `Attribute::from_escaped_bytes()`,
`Attribute::from_str()` and `Attribute::from_escaped_str()` constructors.
- [#416]: Add `borrow()` methods in all event structs which allows to get
a borrowed version of any event

Expand All @@ -42,6 +44,9 @@
- [#363]: Do not generate empty `Event::Text` events
- [#412]: Fix using incorrect encoding if `read_to_end` family of methods or `read_text`
method not found a corresponding end tag and reader has non-UTF-8 encoding
- [#413]: `Attribute::from((&[u8], &[u8]))` was made consistent with `Attribute::from((&str, &str))`
in that both will now escape the value. WARNING: if you were passing escaped values via this
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure how to draw more attention to this but it is a somewhat consequential change and users won't get a compile error.

approach before, your values will be double-escaped and incorrect.

### Misc Changes

Expand Down Expand Up @@ -137,6 +142,7 @@
[#403]: https://github.com/tafia/quick-xml/pull/403
[#407]: https://github.com/tafia/quick-xml/pull/407
[#412]: https://github.com/tafia/quick-xml/pull/412
[#413]: https://github.com/tafia/quick-xml/pull/413
[#416]: https://github.com/tafia/quick-xml/pull/416
[#418]: https://github.com/tafia/quick-xml/pull/418

Expand Down
90 changes: 80 additions & 10 deletions src/events/attributes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,82 @@ pub struct Attribute<'a> {
}

impl<'a> Attribute<'a> {
/// Creates new attribute from text representation.
/// Key is stored as-is, but the value will be escaped.
///
/// # Examples
///
/// ```
/// # use pretty_assertions::assert_eq;
/// use quick_xml::events::attributes::Attribute;
///
/// let features = Attribute::from_str("features", "Bells & whistles");
/// assert_eq!(features.value, "Bells &amp; whistles".as_bytes());
/// ```
pub fn from_str(key: &'a str, val: &'a str) -> Attribute<'a> {
Attribute {
key: QName(key.as_bytes()),
value: escape(val.as_bytes()),
}
}

/// Creates new attribute from text representation.
/// Does not apply any transformation to either key or value.
///
/// # Examples
///
/// ```
/// # use pretty_assertions::assert_eq;
/// use quick_xml::events::attributes::Attribute;
///
/// let features = Attribute::from_escaped_str("features", "Bells &amp; whistles");
/// assert_eq!(features.value, "Bells &amp; whistles".as_bytes());
/// ```
pub fn from_escaped_str(key: &'a str, val: &'a str) -> Attribute<'a> {
Attribute {
key: QName(key.as_bytes()),
value: Cow::from(val.as_bytes()),
}
}

/// Creates new attribute from raw bytes.
/// Key is stored as-is, but the value will be escaped.
///
/// # Examples
///
/// ```
/// # use pretty_assertions::assert_eq;
/// use quick_xml::events::attributes::Attribute;
///
/// let features = Attribute::from_bytes("features".as_bytes(), "Bells & whistles".as_bytes());
/// assert_eq!(features.value, "Bells &amp; whistles".as_bytes());
/// ```
pub fn from_bytes(key: &'a [u8], val: &'a [u8]) -> Attribute<'a> {
Attribute {
key: QName(key),
value: escape(val),
}
}

/// Creates new attribute from raw bytes.
/// Does not apply any transformation to either key or value.
///
/// # Examples
///
/// ```
/// # use pretty_assertions::assert_eq;
/// use quick_xml::events::attributes::Attribute;
///
/// let features = Attribute::from_escaped_bytes("features".as_bytes(), "Bells &amp; whistles".as_bytes());
/// assert_eq!(features.value, "Bells &amp; whistles".as_bytes());
/// ```
pub fn from_escaped_bytes(key: &'a [u8], val: &'a [u8]) -> Attribute<'a> {
Attribute {
key: QName(key),
value: Cow::from(val),
}
}

/// Returns the unescaped value.
///
/// This is normally the value you are interested in. Escape sequences such as `&gt;` are
Expand Down Expand Up @@ -130,22 +206,19 @@ impl<'a> Debug for Attribute<'a> {

impl<'a> From<(&'a [u8], &'a [u8])> for Attribute<'a> {
/// Creates new attribute from raw bytes.
/// Does not apply any transformation to both key and value.
/// Key is stored as-is, but the value will be escaped.
///
/// # Examples
///
/// ```
/// # use pretty_assertions::assert_eq;
/// use quick_xml::events::attributes::Attribute;
///
/// let features = Attribute::from(("features".as_bytes(), "Bells &amp; whistles".as_bytes()));
/// let features = Attribute::from(("features".as_bytes(), "Bells & whistles".as_bytes()));
/// assert_eq!(features.value, "Bells &amp; whistles".as_bytes());
/// ```
fn from(val: (&'a [u8], &'a [u8])) -> Attribute<'a> {
Attribute {
key: QName(val.0),
value: Cow::from(val.1),
}
Attribute::from_bytes(val.0, val.1)
}
}

Expand All @@ -163,10 +236,7 @@ impl<'a> From<(&'a str, &'a str)> for Attribute<'a> {
/// assert_eq!(features.value, "Bells &amp; whistles".as_bytes());
/// ```
fn from(val: (&'a str, &'a str)) -> Attribute<'a> {
Attribute {
key: QName(val.0.as_bytes()),
value: escape(val.1.as_bytes()),
}
Attribute::from_str(val.0, val.1)
}
}

Expand Down