00001 #ifndef SimTK_SimTKCOMMON_XML_H_
00002 #define SimTK_SimTKCOMMON_XML_H_
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
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
00045 class TiXmlNode;
00046 class TiXmlElement;
00047 class TiXmlAttribute;
00048
00261
00262
00263
00264 class SimTK_SimTKCOMMON_EXPORT Xml {
00265 public:
00266
00267
00268 class Attribute;
00269 class Node;
00270 class Comment;
00271 class Unknown;
00272 class Text;
00273 class Element;
00274
00275
00276 class attribute_iterator;
00277
00278
00279
00280 class node_iterator;
00281
00282
00283
00284
00285 class element_iterator;
00286
00292 enum NodeType {
00293 NoNode = 0x00,
00294 ElementNode = 0x01,
00295 TextNode = 0x02,
00296 CommentNode = 0x04,
00297 UnknownNode = 0x08,
00298
00299 NoJunkNodes = ElementNode|TextNode,
00300 JunkNodes = CommentNode|UnknownNode,
00301 AnyNodes = NoJunkNodes|JunkNodes
00302 };
00303
00305 static String getNodeTypeAsString(NodeType type);
00306
00310
00318 Xml();
00319
00323 explicit Xml(const String& pathname);
00324
00326 void clear();
00336 void readFromFile(const String& pathname);
00340 void writeToFile(const String& pathname) const;
00341
00345 void readFromString(const String& xmlDocument);
00349 void readFromString(const char* xmlDocument);
00355 void writeToString(String& xmlDocument, bool compact = false) const;
00358 String getPathname() const;
00370
00382 Element getRootElement();
00383
00386 const String& getRootTag() const;
00389 void setRootTag(const String& tag);
00390
00398 void insertTopLevelNodeAfter (const node_iterator& afterThis,
00399 Node insertThis);
00402 void insertTopLevelNodeBefore(const node_iterator& beforeThis,
00403 Node insertThis);
00409 void eraseTopLevelNode(const node_iterator& deleteThis);
00425 node_iterator node_begin(NodeType allowed=AnyNodes);
00426
00429 node_iterator node_end() const;
00452 String getXmlVersion() const;
00455 String getXmlEncoding() const;
00461 bool getXmlIsStandalone() const;
00462
00465 void setXmlVersion(const String& version);
00468 void setXmlEncoding(const String& encoding);
00473 void setXmlIsStandalone(bool isStandalone);
00476
00477 private:
00478 friend class Node;
00479
00480 class Impl;
00481 const Impl& getImpl() const {assert(impl); return *impl;}
00482 Impl& updImpl() {assert(impl); return *impl;}
00483
00484 Xml& unconst() const {return *const_cast<Xml*>(this);}
00485
00486 Impl* impl;
00487 };
00488
00491
00492 inline std::ostream& operator<<(std::ostream& o, const Xml& xmlDocument) {
00493 String output;
00494 xmlDocument.writeToString(output);
00495 return o << output;
00496 }
00497
00498
00499
00500
00501
00502
00508 class SimTK_SimTKCOMMON_EXPORT Xml::Attribute {
00509 public:
00511 Attribute() : tiAttr(0) {}
00514 Attribute(const String& name, const String& value);
00518 Attribute(const Attribute& src) : tiAttr(src.tiAttr) {}
00523 Attribute& operator=(const Attribute& src)
00524 { if (&src!=this) {clear(); tiAttr=src.tiAttr;} return *this; }
00527 ~Attribute() {clear();}
00529 bool isValid() const {return tiAttr!=0;}
00531 const String& getName() const;
00534 const String& getValue() const;
00537 Attribute& setName(const String& name);
00541 Attribute& setValue(const String& value);
00542
00546 void clear();
00547
00552 void writeToString(String& out) const;
00553
00557 bool operator==(const Attribute& attr) const {return tiAttr==attr.tiAttr;}
00558 bool operator!=(const Attribute& attr) const {return tiAttr!=attr.tiAttr;}
00559
00560
00561 private:
00562 friend class Xml::attribute_iterator;
00563 friend class Xml::Element;
00564
00565 explicit Attribute(TiXmlAttribute* attr) {tiAttr=attr;}
00566 const TiXmlAttribute& getTiAttr() const {assert(tiAttr);return *tiAttr;}
00567 TiXmlAttribute& updTiAttr() {assert(tiAttr);return *tiAttr;}
00568
00569
00570
00571
00572
00573 void setTiAttrPtr(TiXmlAttribute* attr) {tiAttr=attr;}
00574 const TiXmlAttribute* getTiAttrPtr() const {return tiAttr;}
00575 TiXmlAttribute* updTiAttrPtr() {return tiAttr;}
00576
00577 Attribute& unconst() const {return *const_cast<Attribute*>(this);}
00578
00579 TiXmlAttribute* tiAttr;
00580 };
00581
00586
00587 inline std::ostream& operator<<(std::ostream& o, const Xml::Attribute& attr) {
00588 String output;
00589 attr.writeToString(output);
00590 return o << output;
00591 }
00592
00593
00594
00595
00596
00597
00600 class SimTK_SimTKCOMMON_EXPORT Xml::attribute_iterator
00601 : public std::iterator<std::bidirectional_iterator_tag, Xml::Attribute> {
00602 public:
00605 attribute_iterator() {}
00608 explicit attribute_iterator(Attribute& attr) : attr(attr) {}
00611 attribute_iterator(const attribute_iterator& src)
00612 : attr(src->updTiAttrPtr()) {}
00614 ~attribute_iterator() {attr.setTiAttrPtr(0);}
00617 attribute_iterator& operator=(const attribute_iterator& src)
00618 { attr.setTiAttrPtr(src->updTiAttrPtr()); return *this; }
00622 attribute_iterator& operator++();
00626 attribute_iterator operator++(int);
00630 attribute_iterator& operator--();
00634 attribute_iterator operator--(int);
00635
00636
00637
00638
00641 Attribute& operator*() const {return const_cast<Attribute&>(attr);}
00645 Attribute* operator->() const {return const_cast<Attribute*>(&attr);}
00650 bool operator==(const attribute_iterator& other) const
00651 { return other.attr==attr; }
00653 bool operator!=(const attribute_iterator& other) const
00654 { return other.attr!=attr; }
00655
00656
00657 private:
00658 friend class Xml::Element;
00659
00660 explicit attribute_iterator(TiXmlAttribute* ap) : attr(ap) {}
00661
00662 Attribute attr;
00663 };
00664
00665
00666
00667
00668
00669
00693 class SimTK_SimTKCOMMON_EXPORT Xml::Node {
00694 public:
00695
00700
00703 Node() : tiNode(0) {}
00707 Node(const Node& src) : tiNode(src.tiNode) {}
00712 Node& operator=(const Node& src)
00713 { if (&src!=this) {clear(); tiNode=src.tiNode;} return *this; }
00717 ~Node() {clear();}
00721 void clear();
00729
00732 NodeType getNodeType() const;
00733
00735 String getNodeTypeAsString() const;
00736
00739 bool isValid() const {return tiNode != 0;}
00740
00744 bool isTopLevelNode() const;
00745
00750 bool isOrphan() const;
00751
00755 bool hasParentElement() const;
00756
00759 Element getParentElement();
00767
00778 const String& getNodeText() const;
00779
00784 void writeToString(String& out, bool compact=false) const;
00790 bool operator==(const Node& other) const {return other.tiNode==tiNode;}
00792 bool operator!=(const Node& other) const {return other.tiNode!=tiNode;}
00793
00794
00795
00796 protected:
00798 explicit Node(TiXmlNode* tiNode) : tiNode(tiNode) {}
00799
00800 const TiXmlNode& getTiNode() const {assert(tiNode);return *tiNode;}
00801 TiXmlNode& updTiNode() {assert(tiNode);return *tiNode;}
00802
00803
00804
00805
00806 void setTiNodePtr(TiXmlNode* node) {tiNode=node;}
00807 const TiXmlNode* getTiNodePtr() const {return tiNode;}
00808 TiXmlNode* updTiNodePtr() {return tiNode;}
00811
00812 private:
00813 friend class Xml;
00814 friend class Xml::Impl;
00815 friend class Xml::node_iterator;
00816 friend class Xml::Comment;
00817 friend class Xml::Unknown;
00818 friend class Xml::Text;
00819 friend class Xml::Element;
00820
00821 Node& unconst() const {return *const_cast<Node*>(this);}
00822
00823 TiXmlNode* tiNode;
00824 };
00825
00828
00829 inline std::ostream& operator<<(std::ostream& o, const Xml::Node& xmlNode) {
00830 String output;
00831 xmlNode.writeToString(output);
00832 return o << output;
00833 }
00834
00835
00836
00837
00838
00839
00843 class SimTK_SimTKCOMMON_EXPORT Xml::node_iterator
00844 : public std::iterator<std::bidirectional_iterator_tag, Xml::Node> {
00845 public:
00846
00847 explicit node_iterator(NodeType allowed=AnyNodes)
00848 : allowed(allowed) {}
00849 explicit node_iterator(Node& node, NodeType allowed=AnyNodes)
00850 : node(node), allowed(allowed) {}
00851
00854 node_iterator(const node_iterator& src)
00855 : node(*src), allowed(src.allowed) {}
00857 ~node_iterator() {node.setTiNodePtr(0);}
00860 node_iterator& operator=(const node_iterator& src)
00861 { node = *src; allowed = src.allowed; return *this; }
00862
00863 node_iterator& operator++();
00864 node_iterator operator++(int);
00865 node_iterator& operator--();
00866 node_iterator operator--(int);
00867 Node& operator*() {return node;}
00868 Node* operator->() {return &node;}
00869
00870
00871 Node& operator*() const {return const_cast<Node&>(node);}
00872 Node* operator->() const {return const_cast<Node*>(&node);}
00873 bool operator==(const node_iterator& other) const {return other.node==node;}
00874 bool operator!=(const node_iterator& other) const {return other.node!=node;}
00875
00876
00877 protected:
00878 explicit node_iterator(TiXmlNode* tiNode, NodeType allowed=AnyNodes)
00879 : node(tiNode), allowed(allowed) {}
00880 void reassign(TiXmlNode* tiNode)
00881 { node.setTiNodePtr(tiNode); }
00882
00883
00884 private:
00885 friend class Xml;
00886 friend class Xml::Node;
00887 friend class Xml::Element;
00888 friend class Xml::element_iterator;
00889
00890 Node node;
00891 NodeType allowed;
00892 };
00893
00894
00895
00896
00897
00898
00903 class SimTK_SimTKCOMMON_EXPORT Xml::element_iterator
00904 : public Xml::node_iterator {
00905 public:
00906
00909 explicit element_iterator(const String& tag="")
00910 : node_iterator(ElementNode), tag(tag) {}
00913 inline explicit element_iterator(Element& elt, const String& tag="");
00914
00917 element_iterator(const element_iterator& src)
00918 : node_iterator(src), tag(src.tag) {}
00919
00922 element_iterator& operator=(const element_iterator& src)
00923 { upcast()=src; tag = src.tag; return *this; }
00924
00925 element_iterator& operator++();
00926 element_iterator operator++(int);
00927 element_iterator& operator--();
00928 element_iterator operator--(int);
00929 inline Element& operator*() const;
00930 inline Element* operator->() const;
00931
00932 bool operator==(const element_iterator& other) const
00933 { return other.upcast()==upcast();}
00934 bool operator!=(const element_iterator& other) const
00935 { return other.upcast()!=upcast();}
00936
00937
00938 private:
00939 friend class Xml;
00940 friend class Xml::Element;
00941
00942 explicit element_iterator(TiXmlElement* tiElt, const String& tag="")
00943 : node_iterator((TiXmlNode*)tiElt, ElementNode), tag(tag) {}
00944 void reassign(TiXmlElement* tiElt)
00945 { upcast().reassign((TiXmlNode*)tiElt); }
00946
00947 const node_iterator& upcast() const
00948 { return *static_cast<const node_iterator*>(this); }
00949 node_iterator& upcast()
00950 { return *static_cast<node_iterator*>(this); }
00951
00952 String tag;
00953 };
00954
00955
00956
00957
00958
00959
00960
00974 class SimTK_SimTKCOMMON_EXPORT Xml::Element : public Xml::Node {
00975 public:
00976
00984
00987 Element() : Node() {}
00988
01001 explicit Element(const String& tagWord, const String& value="");
01002
01008 template <class T>
01009 Element(const String& tagWord, const T& value)
01010 { new(this) Element(tagWord, String(value)); }
01011
01014 const String& getElementTag() const;
01016 void setElementTag(const String& tag);
01017
01023 void insertNodeBefore(const node_iterator& pos, Node node);
01029 void insertNodeAfter(const node_iterator& pos, Node node);
01035 void eraseNode(const node_iterator& deleteThis);
01049
01055 bool isValueElement() const;
01056
01064 const String& getValue() const;
01065
01071 String& updValue();
01072
01078 void setValue(const String& value);
01079
01083 template <class T>
01084 void setValueAs(const T& value)
01085 { setValue(String(value)); }
01086
01093 template <class T> T getValueAs() const
01094 { T out; convertStringTo(getValue(),out); return out;}
01095
01098 template <class T> void getValueAs(T& out) const
01099 { convertStringTo(getValue(),out); }
01100
01108 const String&
01109 getRequiredElementValue(const String& tag) const
01110 { return unconst().getRequiredElement(tag).getValue(); }
01111
01115 String
01116 getOptionalElementValue(const String& tag, const String& def="") const
01117 { const Element opt(unconst().getOptionalElement(tag));
01118 return opt.isValid() ? opt.getValue() : def; }
01119
01128 template <class T> T
01129 getRequiredElementValueAs(const String& tag) const
01130 { T out; convertStringTo(getRequiredElementValue(tag), out); return out; }
01131
01143 template <class T> T
01144 getOptionalElementValueAs(const String& tag, const T& def) const
01145 { const Element opt(getOptionalElement(tag));
01146 if (!opt.isValid()) return def;
01147 T out; convertStringTo(opt.getValue(), out); return out; }
01157 bool hasAttribute(const String& name) const;
01158
01161 void setAttributeValue(const String& name, const String& value);
01162
01165 void removeAttribute(const String& name);
01166
01169 const String&
01170 getRequiredAttributeValue(const String& name) const
01171 { return unconst().getRequiredAttribute(name).getValue(); }
01172
01179 template <class T> T
01180 getRequiredAttributeValueAs(const String& name) const
01181 { T out; convertStringTo(getRequiredAttributeValue(name),out); return out; }
01182
01189 String
01190 getOptionalAttributeValue(const String& name, const String& def="") const
01191 { Attribute attr = unconst().getOptionalAttribute(name);
01192 if (!attr.isValid()) return def;
01193 return attr.getValue(); }
01194
01205 template <class T> T
01206 getOptionalAttributeValueAs(const String& name, const T& def) const
01207 { Attribute attr = unconst().getOptionalAttribute(name);
01208 if (!attr.isValid()) return def;
01209 T out; convertStringTo(attr.getValue(), out); return out; }
01210
01213 Attribute getRequiredAttribute(const String& name);
01214
01218 Attribute getOptionalAttribute(const String& name);
01219
01228 Array_<Attribute> getAllAttributes()
01229 { return Array_<Attribute>(attribute_begin(), attribute_end()); }
01230
01231
01235 attribute_iterator attribute_begin();
01238 attribute_iterator attribute_end() const;
01252
01254 bool hasElement(const String& tag) const;
01257 bool hasNode(NodeType allowed=AnyNodes) const;
01258
01263 Element getRequiredElement(const String& tag);
01264
01268 Element getOptionalElement(const String& tag);
01269
01277 Array_<Element> getAllElements(const String& tag="")
01278 { return Array_<Element>(element_begin(tag), element_end()); }
01279
01286 Array_<Node> getAllNodes(NodeType allowed=AnyNodes)
01287 { return Array_<Node>(node_begin(allowed), node_end()); }
01288
01293 element_iterator element_begin(const String& tag="");
01296 element_iterator element_end() const;
01297
01302 node_iterator node_begin(NodeType allowed=AnyNodes);
01305 node_iterator node_end() const;
01313 static bool isA(const Node&);
01316 static const Element& getAs(const Node& node);
01319 static Element& getAs(Node& node);
01322
01323 private:
01324 friend class Xml::Node;
01325 friend class Xml::element_iterator;
01326
01327 explicit Element(TiXmlElement* tiElt)
01328 : Node(reinterpret_cast<TiXmlNode*>(tiElt)) {}
01329
01330 TiXmlElement& updTiElement()
01331 { return reinterpret_cast<TiXmlElement&>(updTiNode()); }
01332 const TiXmlElement& getTiElement() const
01333 { return reinterpret_cast<const TiXmlElement&>(getTiNode()); }
01334
01335
01336
01337
01338 const TiXmlElement* getTiElementPtr() const
01339 { return reinterpret_cast<const TiXmlElement*>(getTiNodePtr()); }
01340 TiXmlElement* updTiElementPtr()
01341 { return reinterpret_cast<TiXmlElement*>(updTiNodePtr()); }
01342 void setTiElementPtr(TiXmlElement* elt)
01343 { setTiNodePtr(reinterpret_cast<TiXmlNode*>(elt)); }
01344
01345 Element& unconst() const {return *const_cast<Element*>(this);}
01346
01347
01348
01349 };
01350
01351
01352
01353
01354
01355 inline Xml::element_iterator::element_iterator
01356 (Xml::Element& elt, const String& tag)
01357 : Xml::node_iterator(elt, Xml::ElementNode), tag(tag) {}
01358 inline Xml::Element& Xml::element_iterator::operator*() const
01359 { return Element::getAs(*upcast());}
01360 inline Xml::Element* Xml::element_iterator::operator->() const
01361 { return &Element::getAs(*upcast());}
01362
01363
01364
01365
01366
01367
01368
01370 class SimTK_SimTKCOMMON_EXPORT Xml::Text : public Xml::Node {
01371 public:
01374 Text() : Node() {}
01375
01378 explicit Text(const String& text);
01379
01382 const String& getText() const;
01385 String& updText();
01386
01392 static bool isA(const Node&);
01395 static const Text& getAs(const Node& node);
01398 static Text& getAs(Node& node);
01401
01402 private:
01403
01404 };
01405
01406
01407
01408
01409
01410
01412 class SimTK_SimTKCOMMON_EXPORT Xml::Comment : public Xml::Node {
01413 public:
01416 Comment() : Node() {}
01417
01422 explicit Comment(const String& text);
01423
01424
01430 static bool isA(const Node&);
01433 static const Comment& getAs(const Node& node);
01436 static Comment& getAs(Node& node);
01439
01440 private:
01441
01442 };
01443
01444
01445
01446
01447
01448
01450 class SimTK_SimTKCOMMON_EXPORT Xml::Unknown : public Xml::Node {
01451 public:
01454 Unknown() : Node() {}
01455
01461 explicit Unknown(const String& contents);
01462
01466 Unknown(Element& element, const String& contents)
01467 { new(this) Unknown(contents);
01468 element.insertNodeBefore(element.node_end(), *this); }
01469
01472 const String& getContents() const;
01475 void setContents(const String& contents);
01476
01482 static bool isA(const Node&);
01485 static const Unknown& getAs(const Node& node);
01488 static Unknown& getAs(Node& node);
01491
01492 private:
01493
01494 };
01495
01496 }
01497
01498 #endif // SimTK_SimTKCOMMON_XML_H_
01499
01500