Need some help understanding how to utilize core:encoding/xml

I’d like to create an epg (episode guide) reader/writer to use with my legal OTA channels. So far i’ve enjoyed using Odin for a few other small projects, so I figured since Odin is a data oriented language, xml should be easy enough. With that said, I do not have much experience programmatically processing xml files, so I’m admittedly getting lost in the weeds a bit. Please forgive my ignorance.

So far I’m struggling to understand:

  • The example xml “utf8.xml” contains no english identities for it’s elements, making it difficult for me to reverse engineer any test output I generate.
  • The example odin program does not appear to do anything useful other than generate metrics, which is neat, but makes it difficult to pinpoint where anything practicle is done with (or to) the example xml.
  • Every parse function I try to use on the example xml file “utf8.xml” generates an EOF error. Parsing body says it expects Ident, but gets EOF. Parsing prologue says it expects “Question”. All of these elements exist in the file. Not sure what I’m doing wrong here.

Could anyone point me to an example that opens an xml file and does some basic things? Maybe even an example of creating a new xml tree and saving to file?

Here is a snippet parsing an XML document, checking that the root node is a “map” and then looping through its children:

doc, err := xml.parse(data, xml.Options{
	flags={.Ignore_Unsupported},
	expected_doctype="",
})

if err != nil {
	panic("Failed to parse XML")
}

root := &doc.elements[0]
// Check that root element is a "map" element
assert(root.ident == "map")

// Loop through children
for child_value in root.value {
	switch child in child_value {
	case string:
		// Not expecting text inside root noed
		panic(fmt.tprintf("Unexpected string: \"%s\"", child))
	case xml.Element_ID:
		child_node := &doc.elements[child]
		if child_node.ident == "tileset" {
			// TODO: handle "tileset" node
		} else if child_node.ident == "layer" {
			// TODO: handle "layer" node
		} else {
			// Something we don't care about
			fmt.printfln("Skipping top level node: %s", child_node.ident)
		}
	}
}

You can search through attributes of a node like this:

get_attrib :: proc(element: ^xml.Element, key: string) -> (string, bool) {
	for attrib in element.attribs {
		if attrib.key == key {
			return attrib.val, true
		}
	}

	return "", false
}

Hope that gets you started.

1 Like