一个 lib (quick_xml) 函数 (attributes()) 返回一个类型为 Vec<Cow<'_, [u8]>
的值。
确切的行是 e.attributes().map(|a| a.unwrap().value).collect::<Vec<_>>()
,打印的值 = [[116, 101, 115, 116]]
。
如何将其转换为字符串(在本例中为“test”)以便稍后使用?
答案 0 :(得分:2)
我假设您引用的是 this example。以后,请给我们完整的源代码 - 这样可以更轻松地回答问题。
让我们一步一步来:
e.attributes().map(|a| a.unwrap().value).collect::<Vec<_>>()
^
e
是一个 BytesStart
struct,所以它代表一个开始的 XML 标记,在你的例子中是 <tag1 att1 = "test">
。
e.attributes().map(|a| a.unwrap().value).collect::<Vec<_>>()
^^^^^^^^^^^^
这是the attributes
method of BytesStart
。它返回 the Attributes
struct 表示一个标签具有的一组属性。在您的情况下,这只是一个属性:它具有名称 attr1
和值 test
。
Attributes
is an iterator,这意味着您可以迭代包含的 Attribute
(注意 Attributes
包含多个 Attribute
- 这些不是同一类型!)。如果您想了解有关迭代器的更多信息,您可能需要阅读 the chapter about it in the Rust book。
e.attributes().map(|a| a.unwrap().value).collect::<Vec<_>>()
^^^^^^^^^^^^^^^^^^^^^^^^^
这里,我们称 the map
method of the Iterator
struct。它允许我们通过转换迭代器的每个值来将一个迭代器(在本例中为 Attributes
结构体)转换为另一个迭代器。我们用一个闭包(如果你不知道这是什么,the Rust book also has a chapter about this)来调用它,它接受原始迭代器的一个值并返回新迭代器的转换值。现在,让我们看看那个迭代器:
|a| a.unwrap().value
^^^
这个迭代器接受一个名为 a
的参数,正如我上面所说的,它是原始迭代器包含的类型。我在上面说过 Attributes
包含多个 Attribute
- 虽然这是真的,但它不是全貌,迭代器迭代 Result<Attribute>
,这就是 {{1} 的类型}.
a
正常运行时,|a| a.unwrap().value
^^^^^^^^^^
将始终是包含您的 a
的 Result::Ok
实例,但如果您的 XML 以某种方式无效,Attribute
也可能是一个 {{ 3}} 表示某种解析错误。我们不想关心这里的错误处理,所以我们只调用 Result::Err
返回包含的 a
并在出现错误时发生恐慌。
Argument
|a| a.unwrap().value
^^^^^
结构体包含两个值:the unwrap
method of Result
和 [Attribute
]。我们只对 value
感兴趣,所以让我们选择它。 value
字段的类型为 value
。 Cow 是一个智能指针,具有一些在这里并不真正相关的有趣属性。如果你想了解更多,你可能会对 key
感兴趣(尽管他对 Rust 新手来说可能有点太复杂了)。对于本说明的其余部分,我将假设 Cow<'a, [u8]>
属于 value
类型(对 &[u8]
切片的引用)。
我们现在已经确定闭包返回一个 u8
,因此 &[u8]
返回的迭代器迭代 map
。
&[u8]
现在我们调用 the documentation of Cow
将迭代器转换为集合。集合的类型作为泛型参数给出,为 e.attributes().map(|a| a.unwrap().value).collect::<Vec<_>>()
^^^^^^^^^^^^^^^^^^^
。下划线告诉 rustc 尝试通过上下文找出正确的类型,如果不可能,则输出错误。此处唯一可能的类型是 Vec<_>
,因此,此方法返回 &[u8]
。
您可以使用 the collect
method of Iterator
。这会将 Vec<&[u8]>
值转换为 Attribute
,并且如果属性包含转义序列,也会取消转义它们。
String
请注意,这仍然返回 e.attributes().map(|a| a.unwrap().unescape_and_decode_value(&reader).unwrap()).collect::<Vec<_>>()
,而不是 Vector<String>
。该向量包含分配给该元素的所有属性的值——在本例中,它只是属性值“Test”。
答案 1 :(得分:1)
您可以使用 std::str::from_utf8
将 &[u8]
错误地转换为 &str
:
use std::borrow::Cow;
fn main() {
let s = "test";
let v = s.as_bytes();
let c = Cow::Borrowed(v);
println!("{}", std::str::from_utf8(&*c).unwrap());
}
关键部分是 Cow
的取消引用和重新借用,因为 from_utf8
使用 &[u8]
而不是 Cow
。 Cow
为 Deref
实现 T
,在这种情况下 T
是 [u8]
,因此您可以通过 &[u8]
获得 &*
。
在您的具体示例中,您应该能够通过以下方式获得 Vec<&str>
:
e.attributes().map(|a| std::str::from_utf8(&*a.unwrap().value).unwrap()).collect::<Vec<_>>()