├── .gitattributes
├── .github
└── workflows
│ └── ci.yml
├── .gitignore
├── LICENSE
├── README.md
├── example
├── basic.v
└── xml
├── file_test.xml
├── v.mod
├── xml
└── xml.v
└── xml_test.v
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
--------------------------------------------------------------------------------
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
1 | name: CI
2 | on: [push, pull_request]
3 | jobs:
4 | ubuntu-latest:
5 | runs-on: ubuntu-latest
6 | steps:
7 | - name: Installing V
8 | run: cd ~; git clone https://github.com/vlang/v.git; cd v; make CC=clang; sudo ./v symlink
9 | - uses: actions/checkout@v1
10 | - name: Running Test
11 | env:
12 | VFLAGS: -show_c_cmd -cg
13 | run: v version; v test .
14 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Executables files
2 | xml_test
3 | xml_test.exe
4 |
5 | # Temporary files
6 | fns.txt
7 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 Zen1th
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # vwxml
2 | Pure V library for parsing XML. The data is accessed with a tree API accessible directly within the `Node` struct.
3 |
4 | **This library is now archived.**
5 |
6 | 
7 |
8 | Example: this parses `Hello` to
9 | `Node{name=_root_, text=, childrens=[Node{name=thing, text=, childrens=[Node{name=test, text=Hello, childrens=[], attributes=[]}], attributes=[Attribute{name=abc, value=test}]}], attributes=[]}`
10 | (struct printed with `println`).
11 |
12 | It doesn't support (yet):
13 | - CDATA sections
14 | - Error handling
15 | - Schemas (DTD)
16 |
17 | The features listed above will all be supported soon
18 |
--------------------------------------------------------------------------------
/example/basic.v:
--------------------------------------------------------------------------------
1 | import xml
2 |
3 | fn main() {
4 | node := xml.parse('HelloWorld')
5 | assert(node.childrens.len == 1)
6 | thing := node.childrens[0]
7 | assert(thing.childrens.len == 2)
8 | eprintln('$node')
9 | for t in thing.childrens {
10 | for a in t.attributes {
11 | println(' (a) $a.name = $a.value')
12 | }
13 | println('---> $t.name')
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/example/xml:
--------------------------------------------------------------------------------
1 | ../xml
--------------------------------------------------------------------------------
/file_test.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Hello |
5 | World |
6 |
9 |
10 |
11 | What great parser we have here!
12 |
13 |
14 |
--------------------------------------------------------------------------------
/v.mod:
--------------------------------------------------------------------------------
1 | Module {
2 | name: 'vwxml'
3 | author: 'zenith391'
4 | version: '0.9.0'
5 | repo_url: 'https://github.com/zenith391/vwxml'
6 | vcs: 'git'
7 | tags: ['xml', 'dom']
8 | category: 'xml'
9 | description: 'Pure V library for parsing XML into a DOM'
10 | }
11 |
--------------------------------------------------------------------------------
/xml/xml.v:
--------------------------------------------------------------------------------
1 | module xml
2 |
3 | struct Attribute {
4 | pub mut:
5 | name string
6 | value string
7 | }
8 |
9 | struct ParserState {
10 | mut:
11 | in_head_tag bool
12 | in_attribute_key bool
13 | in_attribute_val bool
14 | attr_key string
15 | attr_val string
16 | in_string bool
17 | head_tag_str string
18 | tag_text string
19 | in_comment bool
20 | word string
21 | tag_attributes []Attribute
22 | }
23 |
24 | struct Node {
25 | pub mut:
26 | attributes []Attribute
27 | name string
28 | text string
29 | childrens []Node
30 | parent &Node
31 | }
32 |
33 | fn can_be_included(ch byte) bool {
34 | return ch != `\n` && ch != `\t` && ch != `\r`
35 | }
36 |
37 | fn unescape_string(str string) string {
38 | return str.replace('<', '<')
39 | .replace('>', '>')
40 | .replace('&', '&')
41 | .replace(''', "'")
42 | .replace('"', '"')
43 | }
44 |
45 | pub fn (mut state ParserState) push_attribute() {
46 | state.tag_attributes << Attribute{state.attr_key, unescape_string(state.attr_val)}
47 | }
48 |
49 | pub fn (attr Attribute) str() string {
50 | return "Attribute{name=" + attr.name + ", value=" + attr.value + "}"
51 | }
52 |
53 | pub fn (node Node) str() string {
54 | return "Node{name=" + node.name + ", text=" + node.text + ", childrens=" + node.childrens.str() + ", attributes=" + node.attributes.str() + "}"
55 | }
56 |
57 | pub fn parse(xml string) Node {
58 | mut root := Node{name: '_root_', parent: &Node(0)}
59 | chars := xml.bytes()
60 |
61 | mut state := ParserState{} // initialize with default parameters
62 | mut curr_node := &root
63 | for ch in chars {
64 | state.word = state.word + ch.str()
65 | if ch == ` ` {
66 | state.word = ''
67 | }
68 | if state.in_comment {
69 | if state.word == '-->' { // comment end
70 | state.in_comment = false
71 | state.word = ''
72 | }
73 | } else {
74 | if state.word == '