Simbody
|
00001 #ifndef SimTK_SimTKCOMMON_XML_H_ 00002 #define SimTK_SimTKCOMMON_XML_H_ 00003 00004 /* -------------------------------------------------------------------------- * 00005 * SimTK Core: SimTKcommon * 00006 * -------------------------------------------------------------------------- * 00007 * This is part of the SimTK Core biosimulation toolkit originating from * 00008 * Simbios, the NIH National Center for Physics-Based Simulation of * 00009 * Biological Structures at Stanford, funded under the NIH Roadmap for * 00010 * Medical Research, grant U54 GM072970. See https://simtk.org. * 00011 * * 00012 * Portions copyright (c) 2010-11 Stanford University and the Authors. * 00013 * Authors: Michael Sherman * 00014 * Contributors: * 00015 * * 00016 * Permission is hereby granted, free of charge, to any person obtaining a * 00017 * copy of this software and associated documentation files (the "Software"), * 00018 * to deal in the Software without restriction, including without limitation * 00019 * the rights to use, copy, modify, merge, publish, distribute, sublicense, * 00020 * and/or sell copies of the Software, and to permit persons to whom the * 00021 * Software is furnished to do so, subject to the following conditions: * 00022 * * 00023 * The above copyright notice and this permission notice shall be included in * 00024 * all copies or substantial portions of the Software. * 00025 * * 00026 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * 00027 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * 00028 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * 00029 * THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * 00030 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * 00031 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE * 00032 * USE OR OTHER DEALINGS IN THE SOFTWARE. * 00033 * -------------------------------------------------------------------------- */ 00034 00035 #include "SimTKcommon/internal/common.h" 00036 #include "SimTKcommon/internal/Array.h" 00037 #include "SimTKcommon/internal/String.h" 00038 00039 #include <iterator> 00040 #include <iostream> 00041 00042 namespace SimTK { 00043 00044 // These are declared but never defined; all TinyXML code is hidden. 00045 class TiXmlNode; 00046 class TiXmlElement; 00047 class TiXmlAttribute; 00048 class TiXmlText; 00049 class TiXmlComment; 00050 class TiXmlUnknown; 00051 00274 //------------------------------------------------------------------------------ 00275 // XML 00276 //------------------------------------------------------------------------------ 00277 class SimTK_SimTKCOMMON_EXPORT Xml { 00278 public: 00279 00280 // These local classes are used to describe the contents of an XML document. 00281 class Attribute; 00282 class Node; // This is the abstract handle type for any node. 00283 class Comment; // These are the concrete node types. 00284 class Unknown; // " 00285 class Text; // " 00286 class Element; // " 00287 00291 typedef Xml Document; 00292 00293 // This provides iteration over all the attributes found in a given element. 00294 class attribute_iterator; 00295 00296 // This provides iteration over all the nodes, or nodes of a certain type, 00297 // at either the Xml document level or over the child nodes of an element. 00298 class node_iterator; 00299 00300 // This provides iteration over all the element nodes that are children 00301 // of a given element, or over the subset of those child elements that has 00302 // a particular tag word. 00303 class element_iterator; 00304 00310 enum NodeType { 00311 NoNode = 0x00, 00312 ElementNode = 0x01, 00313 TextNode = 0x02, 00314 CommentNode = 0x04, 00315 UnknownNode = 0x08, 00316 00317 NoJunkNodes = ElementNode|TextNode, 00318 JunkNodes = CommentNode|UnknownNode, 00319 AnyNodes = NoJunkNodes|JunkNodes 00320 }; 00321 00323 static String getNodeTypeAsString(NodeType type); 00324 00328 00338 Xml(); 00339 00346 explicit Xml(const String& pathname); 00347 00350 Xml(const Xml::Document& source); 00351 00355 Xml::Document& operator=(const Xml::Document& souce); 00356 00358 ~Xml(); 00359 00361 void clear(); 00371 void readFromFile(const String& pathname); 00376 void writeToFile(const String& pathname) const; 00380 void readFromString(const String& xmlDocument); 00384 void readFromString(const char* xmlDocument); 00390 void writeToString(String& xmlDocument, bool compact = false) const; 00395 void setIndentString(const String& indent); 00398 const String& getIndentString() const; 00410 00422 Element getRootElement(); 00423 00426 const String& getRootTag() const; 00429 void setRootTag(const String& tag); 00430 00438 void insertTopLevelNodeAfter (const node_iterator& afterThis, 00439 Node insertThis); 00442 void insertTopLevelNodeBefore(const node_iterator& beforeThis, 00443 Node insertThis); 00449 void eraseTopLevelNode(const node_iterator& deleteThis); 00456 Node removeTopLevelNode(const node_iterator& removeThis); 00472 node_iterator node_begin(NodeType allowed=AnyNodes); 00473 00476 node_iterator node_end() const; 00499 String getXmlVersion() const; 00502 String getXmlEncoding() const; 00508 bool getXmlIsStandalone() const; 00509 00512 void setXmlVersion(const String& version); 00515 void setXmlEncoding(const String& encoding); 00520 void setXmlIsStandalone(bool isStandalone); 00523 //------------------------------------------------------------------------------ 00524 private: 00525 friend class Node; 00526 00527 class Impl; // a private, local class Xml::Impl 00528 const Impl& getImpl() const {assert(impl); return *impl;} 00529 Impl& updImpl() {assert(impl); return *impl;} 00530 00531 Xml& unconst() const {return *const_cast<Xml*>(this);} 00532 00533 Impl* impl; // This is the lone data member. 00534 }; 00535 00540 // Do this inline so we don't have to pass the ostream through the API. 00541 inline std::ostream& operator<<(std::ostream& o, const Xml::Document& doc) { 00542 String output; 00543 doc.writeToString(output); 00544 return o << output; 00545 } 00546 00547 00548 00549 //------------------------------------------------------------------------------ 00550 // XML ATTRIBUTE 00551 //------------------------------------------------------------------------------ 00557 class SimTK_SimTKCOMMON_EXPORT Xml::Attribute { 00558 public: 00560 Attribute() : tiAttr(0) {} 00563 Attribute(const String& name, const String& value); 00567 Attribute(const Attribute& src) : tiAttr(src.tiAttr) {} 00572 Attribute& operator=(const Attribute& src) 00573 { if (&src!=this) {clear(); tiAttr=src.tiAttr;} return *this; } 00577 ~Attribute() {clear();} 00579 bool isValid() const {return tiAttr!=0;} 00584 bool isOrphan() const; 00586 const String& getName() const; 00589 const String& getValue() const; 00592 Attribute& setName(const String& name); 00596 Attribute& setValue(const String& value); 00597 00601 void clear(); 00605 void clearOrphan(); 00606 00611 void writeToString(String& out) const; 00612 00616 bool operator==(const Attribute& attr) const {return tiAttr==attr.tiAttr;} 00617 bool operator!=(const Attribute& attr) const {return tiAttr!=attr.tiAttr;} 00618 00619 //------------------------------------------------------------------------------ 00620 private: 00621 friend class Xml::attribute_iterator; 00622 friend class Xml::Element; 00623 00624 explicit Attribute(TiXmlAttribute* attr) {tiAttr=attr;} 00625 const TiXmlAttribute& getTiAttr() const {assert(tiAttr);return *tiAttr;} 00626 TiXmlAttribute& updTiAttr() {assert(tiAttr);return *tiAttr;} 00627 00628 // Careful; this does not clear the handle before replacing the pointer 00629 // so should not be used if this could be the owner handle of an attribute 00630 // that hasn't ever been added to a document. It is intended for use by 00631 // iterators, whose contained Attributes can never be owners. 00632 void setTiAttrPtr(TiXmlAttribute* attr) {tiAttr=attr;} 00633 const TiXmlAttribute* getTiAttrPtr() const {return tiAttr;} 00634 TiXmlAttribute* updTiAttrPtr() {return tiAttr;} 00635 00636 Attribute& unconst() const {return *const_cast<Attribute*>(this);} 00637 00638 TiXmlAttribute* tiAttr; // this is the lone data member 00639 }; 00640 00645 // Do this inline so we don't have to pass the ostream through the API. 00646 inline std::ostream& operator<<(std::ostream& o, const Xml::Attribute& attr) { 00647 String output; 00648 attr.writeToString(output); 00649 return o << output; 00650 } 00651 00652 00653 00654 //------------------------------------------------------------------------------ 00655 // XML ATTRIBUTE ITERATOR 00656 //------------------------------------------------------------------------------ 00659 class SimTK_SimTKCOMMON_EXPORT Xml::attribute_iterator 00660 : public std::iterator<std::bidirectional_iterator_tag, Xml::Attribute> { 00661 public: 00664 attribute_iterator() {} 00667 explicit attribute_iterator(Attribute& attr) : attr(attr) {} 00670 attribute_iterator(const attribute_iterator& src) 00671 : attr(src->updTiAttrPtr()) {} 00673 ~attribute_iterator() {attr.setTiAttrPtr(0);} 00676 attribute_iterator& operator=(const attribute_iterator& src) 00677 { attr.setTiAttrPtr(src->updTiAttrPtr()); return *this; } 00681 attribute_iterator& operator++(); // prefix 00685 attribute_iterator operator++(int); // postfix 00689 attribute_iterator& operator--(); // prefix 00693 attribute_iterator operator--(int); // postfix 00694 00695 // It's the iterator that's const in these next two methods; it still points 00696 // to a non-const object just like a char* const p. 00697 00700 Attribute& operator*() const {return const_cast<Attribute&>(attr);} 00704 Attribute* operator->() const {return const_cast<Attribute*>(&attr);} 00709 bool operator==(const attribute_iterator& other) const 00710 { return other.attr==attr; } 00712 bool operator!=(const attribute_iterator& other) const 00713 { return other.attr!=attr; } 00714 00715 //------------------------------------------------------------------------------ 00716 private: 00717 friend class Xml::Element; 00718 00719 explicit attribute_iterator(TiXmlAttribute* ap) : attr(ap) {} 00720 00721 Attribute attr; // the lone data member 00722 }; 00723 00724 00725 00726 //------------------------------------------------------------------------------ 00727 // XML NODE 00728 //------------------------------------------------------------------------------ 00752 class SimTK_SimTKCOMMON_EXPORT Xml::Node { 00753 public: 00754 00759 00762 Node() : tiNode(0) {} 00766 Node(const Node& src) : tiNode(src.tiNode) {} 00771 Node& operator=(const Node& src) 00772 { if (&src!=this) {clear(); tiNode=src.tiNode;} return *this; } 00776 Node clone() const; 00780 ~Node() {clear();} 00784 void clear(); 00788 void clearOrphan(); 00796 00799 NodeType getNodeType() const; 00800 00802 String getNodeTypeAsString() const; 00803 00806 bool isValid() const {return tiNode != 0;} 00807 00811 bool isTopLevelNode() const; 00812 00817 bool isOrphan() const; 00818 00822 bool hasParentElement() const; 00823 00826 Element getParentElement(); 00834 00845 const String& getNodeText() const; 00846 00853 void writeToString(String& out, bool compact=false) const; 00859 bool operator==(const Node& other) const {return other.tiNode==tiNode;} 00861 bool operator!=(const Node& other) const {return other.tiNode!=tiNode;} 00862 00863 00864 //------------------------------------------------------------------------------ 00865 protected: // don't let Doxygen see these 00867 explicit Node(TiXmlNode* tiNode) : tiNode(tiNode) {} 00868 00869 const TiXmlNode& getTiNode() const {assert(tiNode);return *tiNode;} 00870 TiXmlNode& updTiNode() {assert(tiNode);return *tiNode;} 00871 00872 // Careful: these "Ptr" methods provide raw access to the contained 00873 // pointer without any cleanup or error checking. In particular, 00874 // setTiNodePtr() does not attempt to delete the current contents. 00875 void setTiNodePtr(TiXmlNode* node) {tiNode=node;} 00876 const TiXmlNode* getTiNodePtr() const {return tiNode;} 00877 TiXmlNode* updTiNodePtr() {return tiNode;} 00880 //------------------------------------------------------------------------------ 00881 private: 00882 friend class Xml; 00883 friend class Xml::Impl; 00884 friend class Xml::node_iterator; 00885 friend class Xml::Comment; 00886 friend class Xml::Unknown; 00887 friend class Xml::Text; 00888 friend class Xml::Element; 00889 00890 Node& unconst() const {return *const_cast<Node*>(this);} 00891 00892 TiXmlNode* tiNode; // the lone data member 00893 }; 00894 00900 // Do this inline so we don't have to pass the ostream through the API. 00901 inline std::ostream& operator<<(std::ostream& o, const Xml::Node& xmlNode) { 00902 String output; 00903 xmlNode.writeToString(output); 00904 return o << output; 00905 } 00906 00907 00908 00909 //------------------------------------------------------------------------------ 00910 // XML NODE ITERATOR 00911 //------------------------------------------------------------------------------ 00915 class SimTK_SimTKCOMMON_EXPORT Xml::node_iterator 00916 : public std::iterator<std::bidirectional_iterator_tag, Xml::Node> { 00917 public: 00918 00919 explicit node_iterator(NodeType allowed=AnyNodes) 00920 : allowed(allowed) {} 00921 explicit node_iterator(Node& node, NodeType allowed=AnyNodes) 00922 : node(node), allowed(allowed) {} 00923 00926 node_iterator(const node_iterator& src) 00927 : node(*src), allowed(src.allowed) {} 00929 ~node_iterator() {node.setTiNodePtr(0);} 00932 node_iterator& operator=(const node_iterator& src) 00933 { node = *src; allowed = src.allowed; return *this; } 00934 00935 node_iterator& operator++(); // prefix 00936 node_iterator operator++(int); // postfix 00937 node_iterator& operator--(); // prefix 00938 node_iterator operator--(int); // postfix 00939 Node& operator*() {return node;} 00940 Node* operator->() {return &node;} 00941 // It's the iterator that's const; it still points to a non-const object 00942 // just like a char* const p. 00943 Node& operator*() const {return const_cast<Node&>(node);} 00944 Node* operator->() const {return const_cast<Node*>(&node);} 00945 bool operator==(const node_iterator& other) const {return other.node==node;} 00946 bool operator!=(const node_iterator& other) const {return other.node!=node;} 00947 00948 //------------------------------------------------------------------------------ 00949 protected: 00950 explicit node_iterator(TiXmlNode* tiNode, NodeType allowed=AnyNodes) 00951 : node(tiNode), allowed(allowed) {} 00952 void reassign(TiXmlNode* tiNode) 00953 { node.setTiNodePtr(tiNode); } 00954 00955 //------------------------------------------------------------------------------ 00956 private: 00957 friend class Xml; 00958 friend class Xml::Node; 00959 friend class Xml::Element; 00960 friend class Xml::element_iterator; 00961 00962 Node node; // data members 00963 NodeType allowed; 00964 }; 00965 00966 00967 00968 //------------------------------------------------------------------------------ 00969 // XML ELEMENT ITERATOR 00970 //------------------------------------------------------------------------------ 00975 class SimTK_SimTKCOMMON_EXPORT Xml::element_iterator 00976 : public Xml::node_iterator { 00977 public: 00978 00981 explicit element_iterator(const String& tag="") 00982 : node_iterator(ElementNode), tag(tag) {} 00985 inline explicit element_iterator(Element& elt, const String& tag=""); // below 00986 00989 element_iterator(const element_iterator& src) 00990 : node_iterator(src), tag(src.tag) {} 00991 00994 element_iterator& operator=(const element_iterator& src) 00995 { upcast()=src; tag = src.tag; return *this; } 00996 00997 element_iterator& operator++(); // prefix 00998 element_iterator operator++(int); // postfix 00999 element_iterator& operator--(); // prefix 01000 element_iterator operator--(int); // postfix 01001 inline Element& operator*() const; // below 01002 inline Element* operator->() const; // below 01003 01004 bool operator==(const element_iterator& other) const 01005 { return other.upcast()==upcast();} 01006 bool operator!=(const element_iterator& other) const 01007 { return other.upcast()!=upcast();} 01008 01009 //------------------------------------------------------------------------------ 01010 private: 01011 friend class Xml; 01012 friend class Xml::Element; 01013 01014 explicit element_iterator(TiXmlElement* tiElt, const String& tag="") 01015 : node_iterator((TiXmlNode*)tiElt, ElementNode), tag(tag) {} 01016 void reassign(TiXmlElement* tiElt) 01017 { upcast().reassign((TiXmlNode*)tiElt); } 01018 01019 const node_iterator& upcast() const 01020 { return *static_cast<const node_iterator*>(this); } 01021 node_iterator& upcast() 01022 { return *static_cast<node_iterator*>(this); } 01023 01024 String tag; // lone data member 01025 }; 01026 01027 01028 01029 01030 //------------------------------------------------------------------------------ 01031 // XML ELEMENT 01032 //------------------------------------------------------------------------------ 01046 class SimTK_SimTKCOMMON_EXPORT Xml::Element : public Xml::Node { 01047 public: 01048 01056 01059 Element() : Node() {} 01060 01073 explicit Element(const String& tagWord, const String& value=""); 01074 01080 template <class T> 01081 Element(const String& tagWord, const T& value) 01082 { new(this) Element(tagWord, String(value)); } 01083 01087 Element clone() const; 01088 01091 const String& getElementTag() const; 01093 void setElementTag(const String& tag); 01094 01100 void insertNodeBefore(const node_iterator& pos, Node node); 01106 void insertNodeAfter(const node_iterator& pos, Node node); 01112 void eraseNode(const node_iterator& deleteThis); 01118 Node removeNode(const node_iterator& removeThis); 01132 01138 bool isValueElement() const; 01139 01147 const String& getValue() const; 01148 01154 String& updValue(); 01155 01161 void setValue(const String& value); 01162 01166 template <class T> 01167 void setValueAs(const T& value) 01168 { setValue(String(value)); } 01169 01176 template <class T> T getValueAs() const 01177 { T out; convertStringTo(getValue(),out); return out;} 01178 01181 template <class T> void getValueAs(T& out) const 01182 { convertStringTo(getValue(),out); } 01183 01191 const String& 01192 getRequiredElementValue(const String& tag) const 01193 { return unconst().getRequiredElement(tag).getValue(); } 01194 01198 String 01199 getOptionalElementValue(const String& tag, const String& def="") const 01200 { const Element opt(unconst().getOptionalElement(tag)); 01201 return opt.isValid() ? opt.getValue() : def; } 01202 01211 template <class T> T 01212 getRequiredElementValueAs(const String& tag) const 01213 { T out; convertStringTo(unconst().getRequiredElementValue(tag), out); 01214 return out; } 01215 01227 template <class T> T 01228 getOptionalElementValueAs(const String& tag, const T& def) const 01229 { const Element opt(unconst().getOptionalElement(tag)); 01230 if (!opt.isValid()) return def; 01231 T out; convertStringTo(opt.getValue(), out); return out; } 01241 bool hasAttribute(const String& name) const; 01242 01245 void setAttributeValue(const String& name, const String& value); 01246 01251 void eraseAttribute(const String& name); 01252 01255 const String& 01256 getRequiredAttributeValue(const String& name) const 01257 { return unconst().getRequiredAttribute(name).getValue(); } 01258 01265 template <class T> T 01266 getRequiredAttributeValueAs(const String& name) const 01267 { T out; convertStringTo(getRequiredAttributeValue(name),out); return out; } 01268 01275 String 01276 getOptionalAttributeValue(const String& name, const String& def="") const 01277 { Attribute attr = unconst().getOptionalAttribute(name); 01278 if (!attr.isValid()) return def; 01279 return attr.getValue(); } 01280 01291 template <class T> T 01292 getOptionalAttributeValueAs(const String& name, const T& def) const 01293 { Attribute attr = unconst().getOptionalAttribute(name); 01294 if (!attr.isValid()) return def; 01295 T out; convertStringTo(attr.getValue(), out); return out; } 01296 01299 Attribute getRequiredAttribute(const String& name); 01300 01304 Attribute getOptionalAttribute(const String& name); 01305 01314 Array_<Attribute> getAllAttributes() 01315 { return Array_<Attribute>(attribute_begin(), attribute_end()); } 01316 01317 01321 attribute_iterator attribute_begin(); 01324 attribute_iterator attribute_end() const; 01338 01340 bool hasElement(const String& tag) const; 01343 bool hasNode(NodeType allowed=AnyNodes) const; 01344 01349 Element getRequiredElement(const String& tag); 01350 01354 Element getOptionalElement(const String& tag); 01355 01363 Array_<Element> getAllElements(const String& tag="") 01364 { return Array_<Element>(element_begin(tag), element_end()); } 01365 01372 Array_<Node> getAllNodes(NodeType allowed=AnyNodes) 01373 { return Array_<Node>(node_begin(allowed), node_end()); } 01374 01379 element_iterator element_begin(const String& tag=""); 01382 element_iterator element_end() const; 01383 01388 node_iterator node_begin(NodeType allowed=AnyNodes); 01391 node_iterator node_end() const; 01399 static bool isA(const Node&); 01402 static const Element& getAs(const Node& node); 01405 static Element& getAs(Node& node); 01408 //------------------------------------------------------------------------------ 01409 private: 01410 friend class Xml::Node; 01411 friend class Xml::element_iterator; 01412 01413 explicit Element(TiXmlElement* tiElt) 01414 : Node(reinterpret_cast<TiXmlNode*>(tiElt)) {} 01415 01416 TiXmlElement& updTiElement() 01417 { return reinterpret_cast<TiXmlElement&>(updTiNode()); } 01418 const TiXmlElement& getTiElement() const 01419 { return reinterpret_cast<const TiXmlElement&>(getTiNode()); } 01420 01421 // Careful: these "Ptr" methods provide raw access to the contained 01422 // pointer without any cleanup or error checking. In particular, 01423 // setTiElementPtr() does not attempt to delete the current contents. 01424 const TiXmlElement* getTiElementPtr() const 01425 { return reinterpret_cast<const TiXmlElement*>(getTiNodePtr()); } 01426 TiXmlElement* updTiElementPtr() 01427 { return reinterpret_cast<TiXmlElement*>(updTiNodePtr()); } 01428 void setTiElementPtr(TiXmlElement* elt) 01429 { setTiNodePtr(reinterpret_cast<TiXmlNode*>(elt)); } 01430 01431 Element& unconst() const {return *const_cast<Element*>(this);} 01432 01433 01434 // no data members; see Node 01435 }; 01436 01437 01438 01439 // A few element_iterator inline definitions had to wait for Element to be 01440 // defined. 01441 inline Xml::element_iterator::element_iterator 01442 (Xml::Element& elt, const String& tag) 01443 : Xml::node_iterator(elt, Xml::ElementNode), tag(tag) {} 01444 inline Xml::Element& Xml::element_iterator::operator*() const 01445 { return Element::getAs(*upcast());} 01446 inline Xml::Element* Xml::element_iterator::operator->() const 01447 { return &Element::getAs(*upcast());} 01448 01449 01450 01451 01452 //------------------------------------------------------------------------------ 01453 // XML TEXT NODE 01454 //------------------------------------------------------------------------------ 01456 class SimTK_SimTKCOMMON_EXPORT Xml::Text : public Xml::Node { 01457 public: 01460 Text() : Node() {} 01461 01464 explicit Text(const String& text); 01465 01469 Text clone() const; 01470 01473 const String& getText() const; 01476 String& updText(); 01477 01483 static bool isA(const Node&); 01486 static const Text& getAs(const Node& node); 01489 static Text& getAs(Node& node); 01492 //------------------------------------------------------------------------------ 01493 private: 01494 // no data members; see Node 01495 01496 explicit Text(TiXmlText* tiText) 01497 : Node(reinterpret_cast<TiXmlNode*>(tiText)) {} 01498 }; 01499 01500 01501 01502 //------------------------------------------------------------------------------ 01503 // XML COMMENT NODE 01504 //------------------------------------------------------------------------------ 01506 class SimTK_SimTKCOMMON_EXPORT Xml::Comment : public Xml::Node { 01507 public: 01510 Comment() : Node() {} 01511 01516 explicit Comment(const String& text); 01517 01521 Comment clone() const; 01522 01528 static bool isA(const Node&); 01531 static const Comment& getAs(const Node& node); 01534 static Comment& getAs(Node& node); 01537 //------------------------------------------------------------------------------ 01538 private: 01539 // no data members; see Node 01540 01541 explicit Comment(TiXmlComment* tiComment) 01542 : Node(reinterpret_cast<TiXmlNode*>(tiComment)) {} 01543 }; 01544 01545 01546 01547 //------------------------------------------------------------------------------ 01548 // XML UNKNOWN NODE 01549 //------------------------------------------------------------------------------ 01551 class SimTK_SimTKCOMMON_EXPORT Xml::Unknown : public Xml::Node { 01552 public: 01555 Unknown() : Node() {} 01556 01562 explicit Unknown(const String& contents); 01563 01567 Unknown(Element& element, const String& contents) 01568 { new(this) Unknown(contents); 01569 element.insertNodeBefore(element.node_end(), *this); } 01570 01574 Unknown clone() const; 01575 01578 const String& getContents() const; 01581 void setContents(const String& contents); 01582 01588 static bool isA(const Node&); 01591 static const Unknown& getAs(const Node& node); 01594 static Unknown& getAs(Node& node); 01597 //------------------------------------------------------------------------------ 01598 private: 01599 // no data members; see Node 01600 01601 explicit Unknown(TiXmlUnknown* tiUnknown) 01602 : Node(reinterpret_cast<TiXmlNode*>(tiUnknown)) {} 01603 }; 01604 01605 } // namespace SimTK 01606 01607 #endif // SimTK_SimTKCOMMON_XML_H_ 01608 01609