I must extract a couple of fields from an XML file and surprise methods to go about it.
First, some context:
I must fetch a libvirt VM’s snapshot info, which is encoded in XML.
I do that withinformation, _ := snap.GetXMLDesc(0)
(information is a string var… so sure, libvirt returns ±8kb information in a single string var).
If I write that string in an xml file, it quantities to 188 traces (7.8kb) of fileds + attributes. I solely want 3 of them, actually.
From numerous readings on the web, I collect that to unmarshall the XML file, I would wish to create an information struct the place I’d map all fields/attributes, and so forth. Absolutely there’s a greater means, after I want about 3 traces of that XML file?
One workaround I thought of is to dump that string var in a file, and “grep” inside that file to get my information, however discovered that un-elegant. There should be a strategy to solely map the data I would like from that file than that ?
Right here’s a pattern of the XML file. Let’s say I needed solely the “mum or dad”, “creation kind” and “kind arch” fileds + attributes, in addition to dumping the XML to a file, I don’t see my means round that.
<description>vmman-generated snapshot</description>
<state>shutoff</state>
<mum or dad>
<identify>0.clear</identify>
</mum or dad>
<creationTime>1667742695</creationTime>
<reminiscence snapshot="no"/>
<disks>
<disk identify="vda" snapshot="inner"/>
</disks>
<area kind="kvm">
<identify>alpinedev</identify>
<uuid>055e3a07-533a-41ee-ae94-cbee5ff404f0</uuid>
<metadata>
<libosinfo:libosinfo xmlns:libosinfo="http://libosinfo.org/xmlns/libvirt/area/1.0">
<libosinfo:os id="http://alpinelinux.org/alpinelinux/3.16"/>
</libosinfo:libosinfo>
</metadata>
<reminiscence unit="KiB">786432</reminiscence>
<currentMemory unit="KiB">786432</currentMemory>
<vcpu placement="static">1</vcpu>
<os>
<kind arch="x86_64" machine="pc-q35-7.0">hvm</kind>
<boot dev='hd'/>
</os>
You would possibly check out “sax” or “stream” parsing of XML.
Alternatively XPath.
If the library you determine to make use of is carried out nicely, reminiscence consumption will likely be comparatively minimal, plus/minus some rubbish collectable artifacts which typically occur whereas looking for information.
1 Like
Oh… I suppose I’ve missed XPath, for some motive ?!. It is rather much like a Python3 lib I’ve used, awhile pack (should be a port/fork). That is the closest I’ve got here throughout for an answer, at present.
I used to be going the workaround means I’ve talked about in my OP, pinching my nostril all the way in which down
Thanks, @NobbZ . I have no idea why I’ve missed XPath in my search ! Don’t care, I’ve an answer, now.
You might have simply outlined a struct with the tags you needed to learn from the information: Go Playground – The Go Programming Language
Simpler but than XPath, @clbanning , thanks. I didn’t suppose you can “partial map” between a struct and an xml doc. I used to be to check it within the playground, and nicely, obtained carried away with @nobbz’s resolution.
Thanks, that works.
Okay, @clbanning , I assumed it labored, nevertheless it doesn’t (notice to self: compiles != works). I’m undecided if it’s my restricted so-far data of GO, or my rusty rememberance of XML docs: right here’s an edited model of the XML I must parse:
<domainsnapshot>
<identify>1.hiya</identify>
<description>vmman-generated snapshot</description>
<state>shutoff</state>
<mum or dad>
<identify>0.clear</identify>
</mum or dad>
<creationTime>1667742695</creationTime>
</domainsnapshot>
Now, I would like the snapshot identify, mum or dad identify (if current) and creationTime.
I’ve constructed the next structs:
kind ParentElement struct {
XMLName xml.Identify `xml:"mum or dad"`
Identify string `xml:"parentname"`
}
kind SnapshotXMLstruct struct {
SnapshotName string `xml:"snapname"`
Creationdate uint64 `xml:"creationdate"`
ParentName ParentElement `xml:"mum or dad",omitempty`
}
ParentName has omitempty set as this tag is likely to be lacking within the XML doc.
My code to retrieve the XML and append the three wanted fields in my very own struct is thus:
var snapXMLdata SnapshotXMLstruct
var snaps []SnapshotXMLstruct
<snip>
snapshots, _ := area.ListAllSnapshots(0)
for _, snap := vary snapshots {
information, _ := snap.GetXMLDesc(0)
err := xml.Unmarshal([]byte(information), &snapXMLdata)
if err != nil {
fmt.Println("Error: ", err)
os.Exit(0)
}
snaps = append(snaps, snapXMLdata)
}
The information
var is non-empty, so it’s not a query of not fetching a legitimate XML doc.
… but, snapXMLdata is empty, and err == nil.
I suppose I’m not getting that easy an idea :-/