extract_information_derived/
extract_information_derived.rs

1//! This example demonstrates how to extract `Document` data into a struct for easy access with the ExtractFields macro.
2
3use nom_xml::{
4    attribute::{Attribute, AttributeValue},
5    io::read_file,
6    tag::Tag,
7    Document, UpdateFields, DocumentIteratorExt
8};
9use nom_xml_derive::ExtractFields;
10use std::fs::File;
11use std::prelude::rust_2021::*;
12
13#[derive(Debug, Default, Clone, ExtractFields, PartialEq)]
14struct Book {
15    #[extract(from_attribute)]
16    isbn: String,
17    authored_by: Option<AuthoredBy>,
18    title: String,
19    genre: String,
20    #[extract(from_tag = "type")]
21    ty: String,
22    series_number: u8,
23    description: Option<String>,
24}
25
26#[derive(Debug, Default, Clone, ExtractFields, PartialEq)]
27struct AuthoredBy {
28    pen_name: Option<String>,
29    authors: Option<Vec<AuthorName>>,
30}
31
32#[derive(Debug, Default, Clone, ExtractFields, PartialEq)]
33struct AuthorName {
34    first_name: String,
35    last_name: String,
36}
37fn main() -> Result<(), Box<dyn std::error::Error>> {
38    let mut file = File::open("examples/TheExpanseSeries.xml")?;
39    let data = read_file(&mut file)?;
40    let (_, doc) = Document::parse_element_by_tag_name(&data, "book", &None)?;
41    let mut book = Book::default();
42    // doc.iter_with_depth(0)
43    //     .filter_map(|record| {
44    //         if let Document::Element(tag, inner_doc, _) = record {
45    //             Some((tag, inner_doc))
46    //         } else {
47    //             None
48    //         }
49    //     })
50    //     .try_for_each(|(tag, inner_doc)| book.update_field(tag, inner_doc))?;
51    // book.update_attribute_fields(&doc);
52    book.update_fields(&doc)?;
53    println!("{book:#?}");
54    Ok(())
55}