using System; using System.Collections.Generic; using System.Xml; namespace mutil { public class XmlExtractor { public const int EC_BEG = 1; // begin of subtree (current node descends) - in public const int EC_CTN = 2; // continue with next sibling element - in / out: data of found element public const int EC_END = 3; // subtree completion (current node ascends); no data - out private XmlDocument docNode; private bool textMode; public XmlNode CurrentNode; public XmlExtractor(object BaseNode = null, bool TextMode = false) { this.CurrentNode = (XmlNode)BaseNode; this.textMode = TextMode; } public void openInput(string input){ this.docNode = new XmlDocument(); this.docNode.Load(input); this.CurrentNode = this.docNode; } public void toTop(){ this.CurrentNode = this.docNode; } public void toParent(){ this.CurrentNode = this.CurrentNode.ParentNode; } public int extractElement(int extr_ctl, out string elem, out string value, out Dictionary attrs) { elem = ""; value = null; attrs = new Dictionary(); XmlNode srh_node; if (extr_ctl == EC_BEG) { srh_node = this.CurrentNode.FirstChild; } else if (extr_ctl == EC_CTN) { srh_node = this.CurrentNode.NextSibling; } else { return EC_END; } // search for next element node if (! this.textMode) { while (srh_node != null) { if (srh_node.NodeType != XmlNodeType.Element) { srh_node = srh_node.NextSibling; } else { break; } } } if (srh_node != null) { // element node found: extract tag name, value and attributes this.CurrentNode = srh_node; this.getCurrentNodeData(out elem, out value, out attrs); return EC_CTN; } else { // terminate / ascend subtree after child extraction if (extr_ctl == EC_CTN) { this.CurrentNode = this.CurrentNode.ParentNode; } return EC_END; } } public void getCurrentNodeData(out string elem, out string value, out Dictionary attrs) { elem = this.CurrentNode.Name; value = null; attrs = new Dictionary(); if (this.textMode) { if (this.CurrentNode.NodeType == XmlNodeType.Text) value = this.CurrentNode.Value; } else { if (this.CurrentNode.InnerText != null) value = this.CurrentNode.InnerText; } if (this.CurrentNode.Attributes != null) { for (int att_idx = 0; att_idx < this.CurrentNode.Attributes.Count; att_idx++) { var att_node = this.CurrentNode.Attributes[att_idx]; attrs[att_node.Name] = this.CurrentNode.Attributes[att_idx].Value; } } } public XmlNode gotoChild(string name) { // return True/False, if child node could be found int cntl = EC_BEG; string elem; string value; Dictionary attrs; while ((cntl = this.extractElement(cntl, out elem, out value, out attrs)) != EC_END) { if (elem == name) return this.CurrentNode; } return null; } public XmlNode requireChild(string name) { // throws exception, if child not present XmlNode child = this.gotoChild(name); if (child == null) throw new Exception("Could not find node "+name); return child; } } }