Registry / RepositoryTypeScriptRustPython
Rollpie
ReadmeFiles
Versions
Info
Download
0.1.199.9 KB2026-09-230.1.098.9 KB2026-09-14
Version
0.1.1
Copyright
Rollpie, Irohabook
Publisher
math
Published
2026-09-23
Size
99.9 KB
Downloads
15
Checksum
e691f02f331393c7b5c3406746caa7ed2636c7af24b1cef422bc957ed16ecd74
Dependencies
None

markup.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
//! XML を読むところ

use folio::xml::{Event, Reader};


/// 読み取った事象を、確かめやすい 1 本の文字列にする
fn trace(source: &str) -> String {
    let mut reader = Reader::over(source.as_bytes().to_vec());
    let mut result = String::new();

    while let Some(event) = reader.next().unwrap() {
        match event {
            Event::Open => result.push_str(&format!("<{}{}>", reader.name(), attribute(&reader))),
            Event::Empty => result.push_str(&format!("<{}{}/>", reader.name(), attribute(&reader))),
            Event::Close => result.push_str(&format!("</{}>", reader.name())),
            Event::Text => result.push_str(&format!("[{}]", reader.text())),
        }
    }

    result
}


/// 試しに使う属性だけを並べる
fn attribute(reader: &Reader) -> String {
    let mut result = String::new();

    for key in ["r", "t", "s", "id", "space", "val"] {
        if let Some(value) = reader.attribute(key) {
            result.push_str(&format!(" {key}={value}"));
        }
    }

    result
}


#[test]
fn tags_and_text_come_back_in_order() {
    assert_eq!(trace("<a>x<b/>y</a>"), "<a>[x]<b/>[y]</a>");
}


#[test]
fn the_declaration_and_comments_are_skipped() {
    assert_eq!(trace("<?xml version=\"1.0\"?><!-- 注記 --><a>1</a>"), "<a>[1]</a>");
}


#[test]
fn a_namespace_prefix_is_dropped() {
    let source = "<x:worksheet xmlns:x=\"n\"><x:row r=\"1\"/></x:worksheet>";
    assert_eq!(trace(source), "<worksheet><row r=1/></worksheet>");
}


#[test]
fn an_attribute_prefix_is_dropped_too() {
    assert_eq!(trace("<sheet r:id=\"rId1\"/>"), "<sheet id=rId1/>");
}


#[test]
fn entities_turn_back_into_characters() {
    assert_eq!(trace("<t>a&amp;b&lt;c&gt;d&quot;e&apos;f</t>"), "<t>[a&b<c>d\"e'f]</t>");
    assert_eq!(trace("<t>&#65;&#x3042;</t>"), "<t>[Aあ]</t>");
}


#[test]
fn cdata_is_taken_as_it_is() {
    assert_eq!(trace("<a><![CDATA[<b>&]]></a>"), "<a>[<b>&]</a>");
}


#[test]
fn a_closing_bracket_inside_a_value_is_not_the_end_of_the_tag() {
    assert_eq!(trace("<a r=\"1&gt;2\"/>"), "<a r=1>2/>");
}


#[test]
fn single_quotes_and_spaces_around_the_equal_sign_are_allowed() {
    assert_eq!(trace("<a  r = 'x' />"), "<a r=x/>");
}


#[test]
fn whitespace_between_tags_is_returned_as_text() {
    assert_eq!(trace("<a>\n\t<b/>\n</a>"), "<a>[\n\t]<b/>[\n]</a>");
}


#[test]
fn a_long_document_is_read_across_the_pieces_it_arrives_in() {
    let source = format!(
        "<sheetData>{}</sheetData>",
        (0..20000)
            .map(|index| format!("<row r=\"{index}\"><c r=\"A{index}\" t=\"s\"><v>{index}</v></c></row>"))
            .collect::<String>()
    );

    let mut reader = Reader::over(source.into_bytes());
    let mut count = 0;
    let mut last = String::new();

    while let Some(event) = reader.next().unwrap() {
        if event == Event::Open && reader.name() == "row" {
            count += 1;
            last = reader.attribute("r").unwrap_or("").to_string();
        }
    }

    assert_eq!(count, 20000);
    assert_eq!(last, "19999");
}


#[test]
fn text_that_is_not_utf8_is_an_error() {
    let mut reader = Reader::over(vec![b'<', b'a', b'>', 0xff, 0xfe, b'<', b'/', b'a', b'>']);
    reader.next().unwrap();
    assert!(reader.next().is_err());
}


#[test]
fn an_unclosed_tag_is_an_error() {
    let mut reader = Reader::over(b"<a".to_vec());
    assert!(reader.next().is_err());
}