X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=src%2FKM_xml.cpp;h=5037391efda1c1bd58dbca586138ed25ebcfaac3;hb=547720ba3ee6c4ca788735deb476e85818794eb0;hp=1148c5369ad87446571c5a5876337a21d16e4982;hpb=3fa7542cd0a774263de265c6a991216ad8fe6960;p=asdcplib.git diff --git a/src/KM_xml.cpp b/src/KM_xml.cpp index 1148c53..5037391 100644 --- a/src/KM_xml.cpp +++ b/src/KM_xml.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2005-2010, John Hurst +Copyright (c) 2005-2015, John Hurst All rights reserved. Redistribution and use in source and binary forms, with or without @@ -61,13 +61,13 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. XERCES_CPP_NAMESPACE_USE -namespace Kumu { - void init_xml_dom(); - typedef std::basic_string XercesString; - bool UTF_8_to_XercesString(const std::string& in_str, XercesString& out_str); - bool UTF_8_to_XercesString(const char* in_str, XercesString& out_str); - bool XercesString_to_UTF_8(const XercesString& in_str, std::string& out_str); - bool XercesString_to_UTF_8(const XMLCh* in_str, std::string& out_str); +extern "C" +{ + void kumu_init_xml_dom(); + bool kumu_UTF_8_to_XercesString(const std::string& in_str, std::basic_string& out_str); + bool kumu_UTF_8_to_XercesString_p(const char* in_str, std::basic_string& out_str); + bool kumu_XercesString_to_UTF_8(const std::basic_string& in_str, std::string& out_str); + bool kumu_XercesString_to_UTF_8_p(const XMLCh* in_str, std::string& out_str); } #endif @@ -186,10 +186,10 @@ Kumu::XMLElement::AddComment(const char* value) // void -Kumu::XMLElement::Render(std::string& outbuf) const +Kumu::XMLElement::Render(std::string& outbuf, const bool& pretty) const { outbuf = "\n"; - RenderElement(outbuf, 0); + RenderElement(outbuf, 0, pretty); } // @@ -202,15 +202,18 @@ add_spacer(std::string& outbuf, i32_t depth) // void -Kumu::XMLElement::RenderElement(std::string& outbuf, ui32_t depth) const +Kumu::XMLElement::RenderElement(std::string& outbuf, const ui32_t& depth, const bool& pretty) const { - add_spacer(outbuf, depth); + if ( pretty ) + { + add_spacer(outbuf, depth); + } outbuf += "<"; outbuf += m_Name; // render attributes - for ( Attr_i i = m_AttrList.begin(); i != m_AttrList.end(); i++ ) + for ( Attr_i i = m_AttrList.begin(); i != m_AttrList.end(); ++i ) { outbuf += " "; outbuf += (*i).name; @@ -228,12 +231,19 @@ Kumu::XMLElement::RenderElement(std::string& outbuf, ui32_t depth) const // render body if ( m_Body.length() > 0 ) - outbuf += m_Body; + { + outbuf += m_Body; + } - for ( Elem_i i = m_ChildList.begin(); i != m_ChildList.end(); i++ ) - (*i)->RenderElement(outbuf, depth + 1); + for ( Elem_i i = m_ChildList.begin(); i != m_ChildList.end(); ++i ) + { + (*i)->RenderElement(outbuf, depth + 1, pretty); + } - add_spacer(outbuf, depth); + if ( pretty ) + { + add_spacer(outbuf, depth); + } } else if ( m_Body.length() > 0 ) { @@ -389,6 +399,20 @@ Kumu::XMLElement::ParseString(const std::string& document) return ParseString(document.c_str(), document.size()); } +// +bool +Kumu::XMLElement::ParseFirstFromString(const ByteString& document) +{ + return ParseFirstFromString((const char*)document.RoData(), document.Length()); +} + +// +bool +Kumu::XMLElement::ParseFirstFromString(const std::string& document) +{ + return ParseFirstFromString(document.c_str(), document.size()); +} + //---------------------------------------------------------------------------------------------------- @@ -515,6 +539,11 @@ xph_namespace_start(void* p, const XML_Char* ns_prefix, const XML_Char* ns_name) bool Kumu::XMLElement::ParseString(const char* document, ui32_t doc_len) { + if ( doc_len == 0 ) + { + return false; + } + XML_Parser Parser = XML_ParserCreateNS("UTF-8", '|'); if ( Parser == 0 ) @@ -531,55 +560,43 @@ Kumu::XMLElement::ParseString(const char* document, ui32_t doc_len) if ( ! XML_Parse(Parser, document, doc_len, 1) ) { - XML_ParserFree(Parser); DefaultLogSink().Error("XML Parse error on line %d: %s\n", XML_GetCurrentLineNumber(Parser), XML_ErrorString(XML_GetErrorCode(Parser))); + XML_ParserFree(Parser); return false; } XML_ParserFree(Parser); if ( ! Ctx.Namespaces->empty() ) - m_NamespaceOwner = (void*)Ctx.Namespaces; + { + m_NamespaceOwner = (void*)Ctx.Namespaces; + } return true; } -//------------------------------------------------------------------------------------------ - -struct xph_test_wrapper -{ - XML_Parser Parser; - bool Status; - - xph_test_wrapper(XML_Parser p) : Parser(p), Status(false) {} -}; - -// expat wrapper functions, map callbacks to IASAXHandler +// expat wrapper functions // static void -xph_test_start(void* p, const XML_Char* name, const XML_Char** attrs) +xph_start_one_shot(void* p, const XML_Char* name, const XML_Char** attrs) { - assert(p); - xph_test_wrapper* Wrapper = (xph_test_wrapper*)p; - - Wrapper->Status = true; - XML_StopParser(Wrapper->Parser, false); + xph_start(p, name, attrs); + XML_Parser parser = (XML_Parser)p; + XML_StopParser(parser, false); } - // bool -Kumu::StringIsXML(const char* document, ui32_t len) +Kumu::XMLElement::ParseFirstFromString(const char* document, ui32_t doc_len) { - if ( document == 0 ) - return false; - - if ( len == 0 ) - len = strlen(document); + if ( doc_len == 0 ) + { + return false; + } - XML_Parser Parser = XML_ParserCreate("UTF-8"); + XML_Parser Parser = XML_ParserCreateNS("UTF-8", '|'); if ( Parser == 0 ) { @@ -587,15 +604,30 @@ Kumu::StringIsXML(const char* document, ui32_t len) return false; } - xph_test_wrapper Wrapper(Parser); - XML_SetUserData(Parser, (void*)&Wrapper); - XML_SetStartElementHandler(Parser, xph_test_start); + ExpatParseContext Ctx(this); + XML_SetUserData(Parser, (void*)&Ctx); + XML_SetElementHandler(Parser, xph_start_one_shot, xph_end); + XML_SetCharacterDataHandler(Parser, xph_char); + XML_SetStartNamespaceDeclHandler(Parser, xph_namespace_start); + + if ( ! XML_Parse(Parser, document, doc_len, 1) ) + { + XML_ParserFree(Parser); + return false; + } - XML_Parse(Parser, document, len, 1); XML_ParserFree(Parser); - return Wrapper.Status; + + if ( ! Ctx.Namespaces->empty() ) + { + m_NamespaceOwner = (void*)Ctx.Namespaces; + } + + return true; } + + #endif //---------------------------------------------------------------------------------------------------- @@ -616,7 +648,7 @@ static const XMLCh sg_label_UTF_8[] = { chLatin_U, chLatin_T, chLatin_F, // void -Kumu::init_xml_dom() +kumu_init_xml_dom() { if ( ! sg_xml_init ) { @@ -656,13 +688,13 @@ Kumu::init_xml_dom() // bool -Kumu::XercesString_to_UTF_8(const Kumu::XercesString& in_str, std::string& out_str) { - return XercesString_to_UTF_8(in_str.c_str(), out_str); +kumu_XercesString_to_UTF_8(const std::basic_string& in_str, std::string& out_str) { + return kumu_XercesString_to_UTF_8_p(in_str.c_str(), out_str); } // bool -Kumu::XercesString_to_UTF_8(const XMLCh* in_str, std::string& out_str) +kumu_XercesString_to_UTF_8_p(const XMLCh* in_str, std::string& out_str) { assert(in_str); assert(sg_xml_init); @@ -699,13 +731,13 @@ Kumu::XercesString_to_UTF_8(const XMLCh* in_str, std::string& out_str) // bool -Kumu::UTF_8_to_XercesString(const std::string& in_str, Kumu::XercesString& out_str) { - return UTF_8_to_XercesString(in_str.c_str(), out_str); +kumu_UTF_8_to_XercesString(const std::string& in_str, std::basic_string& out_str) { + return kumu_UTF_8_to_XercesString_p(in_str.c_str(), out_str); } // bool -Kumu::UTF_8_to_XercesString(const char* in_str, Kumu::XercesString& out_str) +kumu_UTF_8_to_XercesString_p(const char* in_str, std::basic_string& out_str) { assert(in_str); assert(sg_xml_init); @@ -787,7 +819,7 @@ public: ns_prefix = ""; } - ns_map::iterator ni = m_Namespaces->find(ns_name); + ns_map::iterator ni = m_Namespaces->find(ns_prefix); if ( ni != m_Namespaces->end() ) { @@ -813,7 +845,7 @@ public: assert(x_name); std::string tx_name; - if ( ! XercesString_to_UTF_8(x_name, tx_name) ) + if ( ! kumu_XercesString_to_UTF_8(x_name, tx_name) ) m_HasEncodeErrors = true; const char* name = tx_name.c_str(); @@ -843,10 +875,10 @@ public: for ( ui32_t i = 0; i < a_len; i++) { std::string aname, value; - if ( ! XercesString_to_UTF_8(attributes.getName(i), aname) ) + if ( ! kumu_XercesString_to_UTF_8(attributes.getName(i), aname) ) m_HasEncodeErrors = true; - if ( ! XercesString_to_UTF_8(attributes.getValue(i), value) ) + if ( ! kumu_XercesString_to_UTF_8(attributes.getValue(i), value) ) m_HasEncodeErrors = true; const char* x_aname = aname.c_str(); @@ -877,12 +909,16 @@ public: m_Scope.pop(); } +#if XERCES_VERSION_MAJOR < 3 void characters(const XMLCh *const chars, const unsigned int length) +#else + void characters(const XMLCh* const chars, const XMLSize_t length) +#endif { if ( length > 0 ) { std::string tmp; - if ( ! XercesString_to_UTF_8(chars, tmp) ) + if ( ! kumu_XercesString_to_UTF_8(chars, tmp) ) m_HasEncodeErrors = true; m_Scope.top()->AppendBody(tmp); @@ -895,9 +931,11 @@ bool Kumu::XMLElement::ParseString(const char* document, ui32_t doc_len) { if ( doc_len == 0 ) - return false; + { + return false; + } - init_xml_dom(); + kumu_init_xml_dom(); int errorCount = 0; SAXParser* parser = new SAXParser(); @@ -948,37 +986,56 @@ Kumu::XMLElement::ParseString(const char* document, ui32_t doc_len) // bool -Kumu::StringIsXML(const char* document, ui32_t len) +Kumu::XMLElement::ParseFirstFromString(const char* document, ui32_t doc_len) { - if ( document == 0 || *document == 0 ) - return false; + if ( doc_len == 0 ) + { + return false; + } - init_xml_dom(); + kumu_init_xml_dom(); + + int errorCount = 0; + SAXParser* parser = new SAXParser(); - if ( len == 0 ) - len = strlen(document); + parser->setValidationScheme(SAXParser::Val_Always); + parser->setDoNamespaces(true); // optional - SAXParser parser; + MyTreeHandler* docHandler = new MyTreeHandler(this); + parser->setDocumentHandler(docHandler); + parser->setErrorHandler(docHandler); XMLPScanToken token; - bool status = false; try { MemBufInputSource xmlSource(reinterpret_cast(document), - static_cast(len), + static_cast(doc_len), "pidc_rules_file"); - if ( parser.parseFirst(xmlSource, token) ) + if ( ! parser->parseFirst(xmlSource, token) ) + { + ++errorCount; + } + + if ( ! parser->parseNext(token) ) { - if ( parser.parseNext(token) ) - status = true; + ++errorCount; } } catch (...) { + errorCount++; } - return status; + if ( errorCount == 0 ) + { + m_NamespaceOwner = (void*)docHandler->TakeNamespaceMap(); + } + + delete parser; + delete docHandler; + + return errorCount > 0 ? false : true; } @@ -990,15 +1047,14 @@ Kumu::StringIsXML(const char* document, ui32_t len) // bool -Kumu::XMLElement::ParseString(const char* document, ui32_t doc_len) +Kumu::XMLElement::ParseString(const char*, ui32_t) { DefaultLogSink().Error("Kumu compiled without XML parser support.\n"); return false; } -// bool -Kumu::StringIsXML(const char* document, ui32_t len) +Kumu::XMLElement::ParseFirstFromString(const char*, ui32_t) { DefaultLogSink().Error("Kumu compiled without XML parser support.\n"); return false; @@ -1007,6 +1063,50 @@ Kumu::StringIsXML(const char* document, ui32_t len) #endif +//---------------------------------------------------------------------------------------------------- + +// +bool +Kumu::GetXMLDocType(const ByteString& buf, std::string& ns_prefix, std::string& type_name, std::string& namespace_name, + AttributeList& doc_attr_list) +{ + return GetXMLDocType(buf.RoData(), buf.Length(), ns_prefix, type_name, namespace_name, doc_attr_list); +} + +// +bool +Kumu::GetXMLDocType(const std::string& buf, std::string& ns_prefix, std::string& type_name, std::string& namespace_name, + AttributeList& doc_attr_list) +{ + return GetXMLDocType((const byte_t*)buf.c_str(), buf.size(), ns_prefix, type_name, namespace_name, doc_attr_list); +} + +// +bool +Kumu::GetXMLDocType(const byte_t* buf, ui32_t buf_len, std::string& ns_prefix, std::string& type_name, std::string& namespace_name, + AttributeList& doc_attr_list) +{ + XMLElement tmp_element("tmp"); + + if ( ! tmp_element.ParseFirstFromString((const char*)buf, buf_len) ) + { + return false; + } + + const XMLNamespace* ns = tmp_element.Namespace(); + + if ( ns != 0 ) + { + ns_prefix = ns->Prefix(); + namespace_name = ns->Name(); + } + + type_name = tmp_element.GetName(); + doc_attr_list = tmp_element.GetAttributes(); + return true; +} + + // // end KM_xml.cpp //