Registry / RepositoryTypeScriptRustPython
Rollpie
ReadmeFiles
Versions
Info
Download
0.1.098.9 KB2026-09-14
Version
0.1.0
Copyright
Rollpie, Irohabook
Publisher
math
Published
2026-09-14
Size
98.9 KB
Downloads
1
Checksum
bdac84a1e4fe4dd3505b93c2781b1f15833b5189c2e4ee976225fa3c512885cc
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
132
133
134
135
136
137
138
139
//! XML を読むところ

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


/// 読み取った事象を、確かめやすい 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());
}


#[test]
fn escaping_replaces_what_xml_cannot_hold() {
    assert_eq!(escape("a<b>&\"c"), "a&lt;b&gt;&amp;&quot;c");
    assert_eq!(escape("行\tと\n改行"), "行\tと\n改行");
    assert_eq!(escape("落とす\u{1}文字"), "落とす文字");
}