/// <summary> /// Add a new node related to this. Adds a child past the LastChild. /// /// NOTE: the node to be added is passed by pointer, and will be /// henceforth owned (and deleted) by tinyXml. This method is efficient /// and avoids an extra copy, but should be used with care as it /// uses a different memory model than the other insert functions. /// </summary> /// <seealso cref="InsertEndChild"/> public TiXmlNode LinkEndChild(TiXmlNode node) { //assert( node.parent == 0 || node.parent == this ); //assert( node.GetDocument() == 0 || node.GetDocument() == this.GetDocument() ); if (node.Type() == TiXmlNode.NodeType.DOCUMENT) { //delete node; if (GetDocument() != null) { GetDocument().SetError(ErrorType.TIXML_ERROR_DOCUMENT_TOP_ONLY, null, 0, null, TiXmlEncoding.TIXML_ENCODING_UNKNOWN); } return(null); } node.parent = this; node.prev = lastChild; node.next = null; if (lastChild != null) { lastChild.next = node; } else { firstChild = node; // it was an empty list. } lastChild = node; return(node); }
/// <summary> /// Delete a child of this node. /// </summary> public bool RemoveChild(TiXmlNode removeThis) { if (removeThis.parent != this) { //assert(0); return(false); } if (removeThis.next != null) { removeThis.next.prev = removeThis.prev; } else { lastChild = removeThis.prev; } if (removeThis.prev != null) { removeThis.prev.next = removeThis.next; } else { firstChild = removeThis.next; } //delete removeThis; return(true); }
/// <summary> /// Print this Document to a FILE stream. /// </summary> public override void Print(StringBuilder cfile, int depth) { //assert( cfile ); for (TiXmlNode node = FirstChild(); node != null; node = node.NextSibling()) { node.Print(cfile, depth); //fprintf(cfile, "\n"); cfile.Append("\n"); } }
/// <summary> /// The last child of this node matching 'value'. Will be null if there are no children. /// </summary> public TiXmlNode LastChild(string _value) { for (TiXmlNode node = lastChild; node != null; node = node.prev) { if (node.Value().CompareTo(_value) == 0) { return(node); } } return(null); }
/// <summary> /// The first child of this node with the matching 'value'. Will be null if none found. /// </summary> public TiXmlNode FirstChild(string _value) { for (TiXmlNode node = firstChild; node != null; node = node.next) { if (node.Value().CompareTo(_value) == 0) { return(node); } } return(null); }
/// <summary> /// Return a handle to the first child node with the given name. /// </summary> TiXmlHandle FirstChild(string value) { if (node != null) { TiXmlNode child = node.FirstChild(value); if (child != null) { return(new TiXmlHandle(child)); } } return(new TiXmlHandle()); }
/// <summary> /// This flavor of IterateChildren searches for children with a particular 'value' /// </summary> public TiXmlNode IterateChildren(string _value, TiXmlNode previous) { if (previous == null) { return(FirstChild(_value)); } else { //assert( previous.parent == this ); return(previous.NextSibling(_value)); } }
/** Convenience function for easy access to the text inside an element. Although easy * and concise, GetText() is limited compared to getting the TiXmlText child * and accessing it directly. * * If the first child of 'this' is a TiXmlText, the GetText() * returns the character string of the Text node, else null is returned. * * This is a convenient method for getting the text of simple contained text: * @verbatim * <foo>This is text</foo> * const char* str = fooElement.GetText(); * @endverbatim * * 'str' will be a pointer to "This is text". * * Note that this function can be misleading. If the element foo was created from * this XML: * @verbatim * <foo><b>This is text</b></foo> * @endverbatim * * then the value of str would be null. The first child node isn't a text node, it is * another element. From this XML: * @verbatim * <foo>This is <b>text</b></foo> * @endverbatim * GetText() will return "This is ". * * WARNING: GetText() accesses a child node - don't become confused with the * similarly named TiXmlHandle::Text() and TiXmlNode::ToText() which are * safe type casts on the referenced node. */ public string GetText() { TiXmlNode child = this.FirstChild(); if (child != null) { TiXmlText childText = child.ToText(); if (childText != null) { return(childText.Value()); } } return(null); }
/// <summary> /// Walk the XML tree visiting this node and all of its children. /// </summary> public override bool Accept(TiXmlVisitor visitor) { if (visitor.VisitEnter(this)) { for (TiXmlNode node = FirstChild(); node != null; node = node.NextSibling()) { if (!node.Accept(visitor)) { break; } } } return(visitor.VisitExit(this)); }
/// <summary> /// Delete all the children of this node. Does not affect 'this'. /// </summary> public void Clear() { TiXmlNode node = firstChild; //TiXmlNode temp = null; while (node != null) { //temp = node; node = node.next; //delete temp; } firstChild = null; lastChild = null; }
/// <summary> /// Return a handle to the "index" child. The first child is 0, the second 1, etc. /// </summary> TiXmlHandle Child(int count) { if (node != null) { int i; TiXmlNode child = node.FirstChild(); for (i = 0; child != null && i < count; child = child.NextSibling(), ++i) { // nothing } if (child != null) { return(new TiXmlHandle(child)); } } return(new TiXmlHandle()); }
/// <summary> /// Add a new node related to this. Adds a child past the LastChild. /// Returns a pointer to the new object or NULL if an error occurred. /// </summary> public TiXmlNode InsertEndChild(TiXmlNode addThis) { if (addThis.Type() == TiXmlNode.NodeType.DOCUMENT) { if (GetDocument() != null) { GetDocument().SetError(ErrorType.TIXML_ERROR_DOCUMENT_TOP_ONLY, null, 0, null, TiXmlEncoding.TIXML_ENCODING_UNKNOWN); } return(null); } TiXmlNode node = addThis.Clone(); if (node == null) { return(null); } return(LinkEndChild(node)); }
private void CopyTo(TiXmlDocument target) { base.CopyTo(target); target.error = error; target.errorId = errorId; target.errorDesc = errorDesc; target.tabsize = tabsize; target.errorLocation = errorLocation.Clone(); target.useMicrosoftBOM = useMicrosoftBOM; TiXmlNode node = null; for (node = firstChild; node != null; node = node.NextSibling()) { target.LinkEndChild(node.Clone()); } }
protected void CopyTo(TiXmlElement target) { // superclass: base.CopyTo(target); // Element class: // Clone the attributes, then clone the children. TiXmlAttribute attribute = null; for (attribute = attributeSet.First(); attribute != null; attribute = attribute.Next()) { target.SetAttribute(attribute.Name(), attribute.Value()); } TiXmlNode node = null; for (node = firstChild; node != null; node = node.NextSibling()) { target.LinkEndChild(node.Clone()); } }
/// <summary> /// Replace a child of this node. /// Returns a pointer to the new object or NULL if an error occurred. /// </summary> public TiXmlNode ReplaceChild(TiXmlNode replaceThis, TiXmlNode withThis) { if (replaceThis.parent != this) { return(null); } TiXmlNode node = withThis.Clone(); if (node == null) { return(null); } node.next = replaceThis.next; node.prev = replaceThis.prev; if (replaceThis.next != null) { replaceThis.next.prev = node; } else { lastChild = node; } if (replaceThis.prev != null) { replaceThis.prev.next = node; } else { firstChild = node; } //delete replaceThis; node.parent = this; return(node); }
/// <summary> /// Add a new node related to this. Adds a child before the specified child. /// Returns a pointer to the new object or NULL if an error occurred. /// </summary> public TiXmlNode InsertBeforeChild(TiXmlNode beforeThis, TiXmlNode addThis) { if (beforeThis == null || beforeThis.parent != this) { return(null); } if (addThis.Type() == TiXmlNode.NodeType.DOCUMENT) { if (GetDocument() != null) { GetDocument().SetError(ErrorType.TIXML_ERROR_DOCUMENT_TOP_ONLY, null, 0, null, TiXmlEncoding.TIXML_ENCODING_UNKNOWN); } return(null); } TiXmlNode node = addThis.Clone(); if (node == null) { return(null); } node.parent = this; node.next = beforeThis; node.prev = beforeThis.prev; if (beforeThis.prev != null) { beforeThis.prev.next = node; } else { //assert( firstChild == beforeThis ); firstChild = node; } beforeThis.prev = node; return(node); }
/// <summary> /// Add a new node related to this. Adds a child after the specified child. /// Returns a pointer to the new object or NULL if an error occurred. /// </summary> public TiXmlNode InsertAfterChild(TiXmlNode afterThis, TiXmlNode addThis) { if (afterThis == null || afterThis.parent != this) { return(null); } if (addThis.Type() == TiXmlNode.NodeType.DOCUMENT) { if (GetDocument() != null) { GetDocument().SetError(ErrorType.TIXML_ERROR_DOCUMENT_TOP_ONLY, null, 0, null, TiXmlEncoding.TIXML_ENCODING_UNKNOWN); } return(null); } TiXmlNode node = addThis.Clone(); if (node == null) { return(null); } node.parent = this; node.prev = afterThis; node.next = afterThis.next; if (afterThis.next != null) { afterThis.next.prev = node; } else { //assert( lastChild == afterThis ); lastChild = node; } afterThis.next = node; return(node); }
/// <summary> /// Copy constructor /// </summary> TiXmlHandle(TiXmlHandle copy) { this.node = copy.node; }
/// <summary> /// Parse the given null terminated block of xml data. Passing in an encoding to this /// method (either TIXML_ENCODING_LEGACY or TIXML_ENCODING_UTF8 will force TinyXml /// to use that encoding, regardless of what TinyXml might otherwise try to detect. /// </summary> public override int Parse(string p, int index, TiXmlParsingData prevData /* = null*/, int encoding /* = TIXML_DEFAULT_ENCODING*/) { ClearError(); // Parse away, at the document level. Since a document // contains nothing but other tags, most of what happens // here is skipping white space. //if ( !p || !*p ) if (p == null || index < 0 || index >= p.Length) { SetError(ErrorType.TIXML_ERROR_DOCUMENT_EMPTY, null, 0, null, TiXmlEncoding.TIXML_ENCODING_UNKNOWN); return(0); } // Note that, for a document, this needs to come // before the while space skip, so that parsing // starts from the pointer we are given. location.Clear(); if (prevData != null) { location.row = prevData.cursor.row; location.col = prevData.cursor.col; } else { location.row = 0; location.col = 0; } TiXmlParsingData data = new TiXmlParsingData(p, index, TabSize(), location.row, location.col); location = data.Cursor(); #if UNUSED if (encoding == TiXmlEncoding.TIXML_ENCODING_UNKNOWN) { // Check for the Microsoft UTF-8 lead bytes. const unsigned char *pU = (const unsigned char *)p; if (*(pU + 0) && *(pU + 0) == TIXML_UTF_LEAD_0 && *(pU + 1) && *(pU + 1) == TIXML_UTF_LEAD_1 && *(pU + 2) && *(pU + 2) == TIXML_UTF_LEAD_2) { encoding = TIXML_ENCODING_UTF8; useMicrosoftBOM = true; } } #endif index = SkipWhiteSpace(p, index, encoding); //if ( !p ) if (index < 0) { SetError(ErrorType.TIXML_ERROR_DOCUMENT_EMPTY, null, 0, null, TiXmlEncoding.TIXML_ENCODING_UNKNOWN); return(-1); } while (index >= 0 && index < p.Length) { TiXmlNode node = Identify(p, index, encoding); if (node != null) { index = node.Parse(p, index, data, encoding); LinkEndChild(node); } else { break; } // Did we get encoding info? if (encoding == TiXmlEncoding.TIXML_ENCODING_UNKNOWN && node.ToDeclaration() != null) { TiXmlDeclaration dec = node.ToDeclaration(); string enc = dec.Encoding(); //assert( enc ); if (enc.Length == 0 /**enc == 0 */) { encoding = TiXmlEncoding.TIXML_ENCODING_UTF8; } else if (StringEqual(enc, 0, "UTF-8", true, TiXmlEncoding.TIXML_ENCODING_UNKNOWN)) { encoding = TiXmlEncoding.TIXML_ENCODING_UTF8; } else if (StringEqual(enc, 0, "UTF8", true, TiXmlEncoding.TIXML_ENCODING_UNKNOWN)) { encoding = TiXmlEncoding.TIXML_ENCODING_UTF8; // incorrect, but be nice } else { encoding = TiXmlEncoding.TIXML_ENCODING_LEGACY; } } index = SkipWhiteSpace(p, index, encoding); } // Was this empty? if (firstChild == null) { SetError(ErrorType.TIXML_ERROR_DOCUMENT_EMPTY, null, 0, null, encoding); return(INVALID_STRING_INDEX); } // All is well. return(index); }
/// <summary> /// [internal use] /// Reads the "value" of the element -- another element, or text. /// This should terminate with the current end tag. /// </summary> protected int ReadValue(string p, int index, TiXmlParsingData data, int encoding) { TiXmlDocument document = GetDocument(); // Read in text and elements in any order. int pWithWhiteSpace = index; index = SkipWhiteSpace(p, index, encoding); while (index >= 0 && index < p.Length) { if (p[index] != '<') { // Take what we have, make a text element. TiXmlText textNode = new TiXmlText(""); if (textNode == null) { if (document == null) { document.SetError(ErrorType.TIXML_ERROR_OUT_OF_MEMORY, null, 0, null, encoding); } return(INVALID_STRING_INDEX); } if (IsWhiteSpaceCondensed()) { index = textNode.Parse(p, index, data, encoding); } else { // Special case: we want to keep the white space // so that leading spaces aren't removed. index = textNode.Parse(p, pWithWhiteSpace, data, encoding); } if (!textNode.Blank()) { LinkEndChild(textNode); } //else // delete textNode; } else { // We hit a '<' // Have we hit a new element or an end tag? This could also be // a TiXmlText in the "CDATA" style. if (StringEqual(p, index, "</", false, encoding)) { return(index); } else { TiXmlNode node = Identify(p, index, encoding); if (node != null) { index = node.Parse(p, index, data, encoding); LinkEndChild(node); } else { return(-1); } } } pWithWhiteSpace = index; index = SkipWhiteSpace(p, index, encoding); } if (index < 0) { if (document != null) { document.SetError(ErrorType.TIXML_ERROR_READING_ELEMENT_VALUE, null, 0, null, encoding); } } return(index); }
/// <summary> /// Print the Element to a FILE stream. /// </summary> public override void Print(StringBuilder cfile, int depth) { //assert( cfile ); for (int i = 0; i < depth; i++) { //fprintf( cfile, " " ); cfile.Append(" "); } cfile.Append("<"); cfile.Append(value); //fprintf( cfile, "<%s", value.c_str() ); for (TiXmlAttribute attrib = attributeSet.First(); attrib != null; attrib = attrib.Next()) { cfile.Append(" "); //fprintf(cfile, " "); attrib.Print(cfile, depth); } // There are 3 different formatting approaches: // 1) An element without children is printed as a <foo /> node // 2) An element with only a text child is printed as <foo> text </foo> // 3) An element with children is printed on multiple lines. if (firstChild == null) { //fprintf(cfile, " />"); cfile.Append(" />"); } else if (firstChild == lastChild && firstChild.ToText() != null) { //fprintf(cfile, ">"); cfile.Append(">"); firstChild.Print(cfile, depth + 1); //fprintf(cfile, "</%s>", value.c_str()); cfile.Append("</"); cfile.Append(value); cfile.Append(">"); } else { //fprintf(cfile, ">"); cfile.Append(">"); for (TiXmlNode node = firstChild; node != null; node = node.NextSibling()) { if (node.ToText() == null) { //fprintf(cfile, "\n"); cfile.Append("\n"); } node.Print(cfile, depth + 1); } //fprintf(cfile, "\n"); cfile.Append("\n"); for (int i = 0; i < depth; ++i) { //fprintf(cfile, " "); cfile.Append(" "); } //fprintf(cfile, "</%s>", value.c_str()); cfile.Append("</"); cfile.Append(value); cfile.Append(">"); } }
/// <summary> /// Create a handle from any node (at any depth of the tree.) This can be a null pointer. /// </summary> TiXmlHandle(TiXmlNode _node) { this.node = _node; }
/// <summary> /// Copy to the allocated object. Shared functionality between Clone, Copy constructor, and the assignment operator. /// </summary> protected void CopyTo(TiXmlNode target) { target.SetValue(value); target.userData = userData; }
/// <summary> /// Figure out what is at *p, and parse it. Returns null if it is not an xml node. /// </summary> protected TiXmlNode Identify(string p, int index, int encoding) { TiXmlNode returnNode = null; index = SkipWhiteSpace(p, index, encoding); if (p == null || index < 0 || index >= p.Length || p[index] != '<') { return(null); } TiXmlDocument doc = GetDocument(); index = SkipWhiteSpace(p, index, encoding); if (index < 0 || index >= p.Length) { return(null); } // What is this thing? // - Elements start with a letter or underscore, but xml is reserved. // - Comments: <!-- // - Decleration: <?xml // - Everthing else is unknown to tinyxml. // const string xmlHeader = "<?xml"; const string commentHeader = "<!--"; const string dtdHeader = "<!"; const string cdataHeader = "<![CDATA["; if (StringEqual(p, index, xmlHeader, true, encoding)) { #if UNUSED TIXML_LOG("XML parsing Declaration\n"); #endif returnNode = new TiXmlDeclaration(); } else if (StringEqual(p, index, commentHeader, false, encoding)) { #if UNUSED TIXML_LOG("XML parsing Comment\n"); #endif returnNode = new TiXmlComment(); } else if (StringEqual(p, index, cdataHeader, false, encoding)) { #if UNUSED TIXML_LOG("XML parsing CDATA\n"); #endif TiXmlText text = new TiXmlText(""); text.SetCDATA(true); returnNode = text; } else if (StringEqual(p, index, dtdHeader, false, encoding)) { #if UNUSED TIXML_LOG("XML parsing Unknown(1)\n"); #endif returnNode = new TiXmlUnknown(); } else if (IsAlpha(p[index + 1], encoding) || p[index + 1] == '_') { #if UNUSED TIXML_LOG("XML parsing Element\n"); #endif returnNode = new TiXmlElement(""); } else { #if UNUSED TIXML_LOG("XML parsing Unknown(2)\n"); #endif returnNode = new TiXmlUnknown(); } if (returnNode != null) { // Set the parent, so it can report errors returnNode.parent = this; } else { if (doc != null) { doc.SetError(ErrorType.TIXML_ERROR_OUT_OF_MEMORY, null, 0, null, TiXmlEncoding.TIXML_ENCODING_UNKNOWN); } } return(returnNode); }