// file : XSCRT/XML.hpp // author : Boris Kolpackov // cvs-id : $Id$ #ifndef XSCRT_XML_HPP #define XSCRT_XML_HPP #include #include #include //@@ VC6 #if defined (_MSC_VER) && (_MSC_VER < 1300) namespace std { typedef ::size_t size_t; } #endif namespace XSCRT { namespace XML { //@@ VC6 // template std::basic_string transcode (XMLCh const* s, C*); template XMLCh* transcode (std::basic_string const& s); // // // class string { public : template string (std::basic_string const& s) : s_ (XSCRT::XML::transcode (s)) { } template string (C const* s) : s_ (XSCRT::XML::transcode (s)) { } ~string () { delete[] s_; } XMLCh const* c_str () const { return s_; } private : XMLCh* s_; }; template <> inline std::basic_string transcode (XMLCh const* s, char*) { if (s == 0) return std::basic_string (); char* buf = xercesc::XMLString::transcode (s); std::basic_string r (buf); xercesc::XMLString::release (&buf); return r; } template <> inline std::basic_string transcode (XMLCh const* s, wchar_t*) { if (s == 0) return std::basic_string (); // std::wcerr << s << std::endl; std::basic_string r (xercesc::XMLString::stringLen (s), L'0'); for (std::size_t i (0); *s != XMLCh (0); ++s, ++i) { r[i] = *s; } return r; } template <> inline XMLCh* transcode (std::basic_string const& s) { return xercesc::XMLString::transcode (s.c_str ()); } template <> inline XMLCh* transcode (std::basic_string const& s) { //@@ VC6 std::size_t l = s.length (); //@@ VC6 XMLCh* r = new XMLCh[l + 1]; XMLCh* ir = r; for (std::size_t i (0); i < l; ++ir, ++i) { *ir = static_cast(s[i]); //std::wcerr << s[i] << "->" << *ir << std::endl; } *ir = XMLCh (0); // std::wcerr << r << std::endl; return r; } template class Element; template std::basic_string ns_prefix (std::basic_string const& ns, Element const& e); // Casting helpers, made necessary by the Xerces project's braindead // avoidance of RTTI. template struct dom_traits; // Specializations for different node types template <> struct dom_traits { enum { node_type = xercesc::DOMNode::ELEMENT_NODE }; }; template <> struct dom_traits { enum { node_type = xercesc::DOMNode::ATTRIBUTE_NODE }; }; template DERIVED_PTR dom_cast (xercesc::DOMNode *node) { DERIVED_PTR elem = 0; if ((node != 0) && (node->getNodeType () == dom_traits::node_type)) { elem = reinterpret_cast (node); } return elem; } template class Element { typedef std::basic_string string_; public: Element (xercesc::DOMElement const* e) : e_ (0), ce_ (e), name_ (transcode (e->getLocalName (), 0)), namespace__ (transcode (e->getNamespaceURI (), 0)) { } Element (xercesc::DOMElement* e) : e_ (e), ce_ (e), name_ (transcode (e->getLocalName (), 0)), namespace__ (transcode (e->getNamespaceURI (), 0)) { } Element (string_ const& name, Element& parent) : e_ (0), ce_ (0), name_ (name) { xercesc::DOMDocument* doc ( parent.dom_element ()->getOwnerDocument ()); e_ = doc->createElement (string (name).c_str ()); parent.dom_element ()->appendChild (e_); ce_ = e_; } Element (string_ const& name, string_ const& ns, Element& parent) : e_ (0), ce_ (0), name_ (name), namespace__ (ns) { string_ prefix (ns_prefix (ns, parent)); xercesc::DOMDocument* doc ( parent.dom_element ()->getOwnerDocument ()); e_ = doc->createElementNS ( string (ns).c_str (), string (prefix.empty () ? name : prefix + string_ (1, ':') + name).c_str ()); parent.dom_element ()->appendChild (e_); ce_ = e_; } public: string_ name () const { return name_; } string_ namespace_ () const { return namespace__; } public: Element parent () const { return dom_cast (ce_->getParentNode ()); } public: string_ value () const { return XML::transcode (dom_element ()->getTextContent (), 0); } void value (string_ const& v) { xercesc::DOMText* text ( dom_element ()->getOwnerDocument ()->createTextNode( string (v).c_str ())); dom_element ()->appendChild (text); } public: string_ operator[] (string_ const& s) const { //@@ VC6 XMLCh const* value = ce_->getAttribute (string (s).c_str ()); return transcode (value, 0); } public: xercesc::DOMElement const* dom_element () const { return ce_; } xercesc::DOMElement* dom_element () { return e_; } private: xercesc::DOMElement* e_; xercesc::DOMElement const* ce_; string_ name_; string_ namespace__; }; template class Attribute { typedef std::basic_string string_; public: Attribute (xercesc::DOMAttr const* a) : a_ (0), ca_ (a), name_ (transcode (a->getLocalName (), 0)), value_ (transcode (a->getValue (), 0)) { } Attribute (xercesc::DOMAttr* a) : a_ (a), ca_ (a), name_ (transcode (a->getLocalName (), 0)), value_ (transcode (a->getValue (), 0)) { } Attribute (string_ const& name, string_ const& v, Element& parent) : a_ (0), ca_ (0), name_ (name), value_ () { xercesc::DOMDocument* doc ( parent.dom_element ()->getOwnerDocument ()); a_ = doc->createAttribute (string (name).c_str ()); value (v); parent.dom_element ()->setAttributeNode (a_); ca_ = a_; } Attribute (string_ const& name, string_ const& ns, string_ const& v, Element& parent) : a_ (0), ca_ (0), name_ (name), value_ () { string_ prefix (ns_prefix (ns, parent)); xercesc::DOMDocument* doc ( parent.dom_element ()->getOwnerDocument ()); a_ = doc->createAttributeNS ( string (ns).c_str (), string (prefix.empty () ? name : prefix + string_ (1, ':') + name).c_str ()); value (v); parent.dom_element ()->setAttributeNodeNS (a_); ca_ = a_; } string_ name () const { return name_; } string_ value () const { return value_; } void value (string_ const& v) { value_ = v; a_->setValue (string (v).c_str ()); } public: xercesc::DOMAttr const* dom_attribute () const { return ca_; } xercesc::DOMAttr* dom_attribute () { return a_; } private: private: xercesc::DOMAttr* a_; xercesc::DOMAttr const* ca_; string_ name_; string_ value_; }; template std::basic_string prefix (std::basic_string const& n) { std::size_t i (0); while (i < n.length () && n[i] != ':') ++i; //std::wcerr << "prefix " << n << " " // << std::wstring (n, i == n.length () ? i : 0, i) << std::endl; return std::basic_string (n, i == n.length () ? i : 0, i); } template std::basic_string uq_name (std::basic_string const& n) { std::size_t i (0); while (i < n.length () && n[i] != ':') ++i; return std::basic_string (n.c_str () + (i == n.length () ? 0 : i + 1)); } template std::basic_string ns_name (Element const& e, std::basic_string const& n) { std::basic_string wp (prefix (n)); //@@ VC6 XMLCh const* xns = e.dom_element ()->lookupNamespaceURI ( wp.empty () ? 0 : string (wp).c_str ()); std::basic_string ns ( xns ? transcode (xns, 0) : std::basic_string ()); return ns; } template std::basic_string fq_name (Element const& e, std::basic_string const& n) { std::basic_string ns (ns_name (e, n)); std::basic_string un (uq_name (n)); return ns.empty () ? un : (ns + C ('#') + un); } class no_prefix {}; template std::basic_string ns_prefix (std::basic_string const& ns, Element const& e) { string xns (ns); XMLCh const* p ( e.dom_element ()->lookupNamespacePrefix (xns.c_str (), false)); if (p == 0) { bool r (e.dom_element ()->isDefaultNamespace (xns.c_str ())); if (r) { return std::basic_string (); } else { throw no_prefix (); } } return transcode (p, 0); } } } #include "XSCRT/XML.ipp" #include "XSCRT/XML.tpp" #endif // XSCRT_XML_HPP