/*
-Copyright (c) 2005-2006, John Hurst
+Copyright (c) 2005-2015, John Hurst
All rights reserved.
Redistribution and use in source and binary forms, with or without
#include <KM_xml.h>
#include <KM_log.h>
+#include <KM_mutex.h>
#include <stack>
#include <map>
-#ifdef ASDCP_USE_EXPAT
+#ifdef HAVE_EXPAT
+# ifdef HAVE_XERCES_C
+# error "Both HAVE_EXPAT and HAVE_XERCES_C defined"
+# endif
#include <expat.h>
#endif
+#ifdef HAVE_XERCES_C
+# ifdef HAVE_EXPAT
+# error "Both HAVE_EXPAT and HAVE_XERCES_C defined"
+# endif
+
+#include <xercesc/util/PlatformUtils.hpp>
+#include <xercesc/util/XMLString.hpp>
+#include <xercesc/util/TransService.hpp>
+#include <xercesc/sax/AttributeList.hpp>
+#include <xercesc/sax/HandlerBase.hpp>
+#include <xercesc/sax/ErrorHandler.hpp>
+#include <xercesc/sax/SAXParseException.hpp>
+#include <xercesc/parsers/SAXParser.hpp>
+#include <xercesc/framework/MemBufInputSource.hpp>
+#include <xercesc/framework/XMLPScanToken.hpp>
+
+
+XERCES_CPP_NAMESPACE_USE
+
+extern "C"
+{
+ void kumu_init_xml_dom();
+ bool kumu_UTF_8_to_XercesString(const std::string& in_str, std::basic_string<XMLCh>& out_str);
+ bool kumu_UTF_8_to_XercesString_p(const char* in_str, std::basic_string<XMLCh>& out_str);
+ bool kumu_XercesString_to_UTF_8(const std::basic_string<XMLCh>& in_str, std::string& out_str);
+ bool kumu_XercesString_to_UTF_8_p(const XMLCh* in_str, std::string& out_str);
+}
+
+#endif
+
using namespace Kumu;
class ns_map : public std::map<std::string, XMLNamespace*>
{
public:
- ns_map() {}
~ns_map()
{
- ns_map::iterator ni = begin();
-
- while (ni != end() )
+ while ( ! empty() )
{
- // fprintf(stderr, "deleting namespace %s:%s\n", ni->second->Prefix().c_str(), ni->second->Name().c_str());
+ ns_map::iterator ni = begin();
delete ni->second;
- ni++;
+ erase(ni);
}
}
};
for ( Elem_i i = m_ChildList.begin(); i != m_ChildList.end(); i++ )
delete *i;
- if ( m_NamespaceOwner != 0 )
- delete (ns_map*)m_NamespaceOwner;
+ delete (ns_map*)m_NamespaceOwner;
}
//
m_AttrList.push_back(TmpVal);
}
+//
+Kumu::XMLElement*
+Kumu::XMLElement::AddChild(Kumu::XMLElement* element)
+{
+ m_ChildList.push_back(element); // takes posession!
+ return element;
+}
+
//
Kumu::XMLElement*
Kumu::XMLElement::AddChild(const char* name)
m_Body += value;
}
+//
+void
+Kumu::XMLElement::SetBody(const std::string& value)
+{
+ m_Body = value;
+}
+
//
Kumu::XMLElement*
Kumu::XMLElement::AddChildWithContent(const char* name, const char* value)
//
void
-Kumu::XMLElement::Render(std::string& outbuf) const
+Kumu::XMLElement::Render(std::string& outbuf, const bool& pretty) const
{
outbuf = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
- RenderElement(outbuf, 0);
+ RenderElement(outbuf, 0, pretty);
}
//
//
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;
// 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 )
{
return outList;
}
+//
+void
+Kumu::XMLElement::DeleteAttributes()
+{
+ m_AttrList.clear();
+}
+
+//
+void
+Kumu::XMLElement::DeleteAttrWithName(const char* name)
+{
+ assert(name);
+ AttributeList::iterator i = m_AttrList.begin();
+
+ while ( i != m_AttrList.end() )
+ {
+ if ( i->name == std::string(name) )
+ m_AttrList.erase(i++);
+ else
+ ++i;
+ }
+}
+
+//
+void
+Kumu::XMLElement::DeleteChildren()
+{
+ while ( ! m_ChildList.empty() )
+ {
+ delete m_ChildList.back();
+ m_ChildList.pop_back();
+ }
+}
+
+//
+void
+Kumu::XMLElement::DeleteChild(const XMLElement* element)
+{
+ if ( element != 0 )
+ {
+ for ( ElementList::iterator i = m_ChildList.begin(); i != m_ChildList.end(); i++ )
+ {
+ if ( *i == element )
+ {
+ delete *i;
+ m_ChildList.erase(i);
+ return;
+ }
+ }
+ }
+}
+
+//
+void
+Kumu::XMLElement::ForgetChild(const XMLElement* element)
+{
+ if ( element != 0 )
+ {
+ for ( ElementList::iterator i = m_ChildList.begin(); i != m_ChildList.end(); i++ )
+ {
+ if ( *i == element )
+ {
+ m_ChildList.erase(i);
+ return;
+ }
+ }
+ }
+}
+
+//
+bool
+Kumu::XMLElement::ParseString(const ByteString& document)
+{
+ return ParseString((const char*)document.RoData(), document.Length());
+}
+
+//
+bool
+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());
+}
+
+
//----------------------------------------------------------------------------------------------------
-#ifdef ASDCP_USE_EXPAT
+#ifdef HAVE_EXPAT
class ExpatParseContext
//
bool
-Kumu::XMLElement::ParseString(const std::string& document)
+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 )
XML_SetCharacterDataHandler(Parser, xph_char);
XML_SetStartNamespaceDeclHandler(Parser, xph_namespace_start);
- if ( ! XML_Parse(Parser, document.c_str(), document.size(), 1) )
+ 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;
}
-//------------------------------------------------------------------------------------------
+// expat wrapper functions
+//
+static void
+xph_start_one_shot(void* p, const XML_Char* name, const XML_Char** attrs)
+{
+ xph_start(p, name, attrs);
+ XML_Parser parser = (XML_Parser)p;
+ XML_StopParser(parser, false);
+}
-struct xph_test_wrapper
+//
+bool
+Kumu::XMLElement::ParseFirstFromString(const char* document, ui32_t doc_len)
{
- XML_Parser Parser;
- bool Status;
+ if ( doc_len == 0 )
+ {
+ return false;
+ }
- xph_test_wrapper(XML_Parser p) : Parser(p), Status(false) {}
-};
+ XML_Parser Parser = XML_ParserCreateNS("UTF-8", '|');
-// expat wrapper functions, map callbacks to IASAXHandler
-//
-static void
-xph_test_start(void* p, const XML_Char* name, const XML_Char** attrs)
+ if ( Parser == 0 )
+ {
+ DefaultLogSink().Error("Error allocating memory for XML parser.\n");
+ return false;
+ }
+
+ 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_ParserFree(Parser);
+
+ if ( ! Ctx.Namespaces->empty() )
+ {
+ m_NamespaceOwner = (void*)Ctx.Namespaces;
+ }
+
+ return true;
+}
+
+
+
+#endif
+
+//----------------------------------------------------------------------------------------------------
+
+#ifdef HAVE_XERCES_C
+
+static Mutex sg_xerces_init_lock; // protect the xerces initialized
+static bool sg_xml_init = false; // signal initialization
+static Mutex sg_coder_lock; // protect the transcoder context
+static XMLTranscoder* sg_coder = 0;
+static const int sg_coder_buf_len = 128 * 1024;
+static char sg_coder_buf[sg_coder_buf_len + 8];
+static unsigned char sg_coder_counts[sg_coder_buf_len / sizeof(XMLCh)]; // see XMLTranscoder::transcodeFrom
+
+static const XMLCh sg_LS[] = { chLatin_L, chLatin_S, chNull };
+static const XMLCh sg_label_UTF_8[] = { chLatin_U, chLatin_T, chLatin_F,
+ chDash, chDigit_8, chNull};
+
+//
+void
+kumu_init_xml_dom()
{
- assert(p);
- xph_test_wrapper* Wrapper = (xph_test_wrapper*)p;
+ if ( ! sg_xml_init )
+ {
+ AutoMutex AL(sg_xerces_init_lock);
- Wrapper->Status = true;
- XML_StopParser(Wrapper->Parser, false);
+ if ( ! sg_xml_init )
+ {
+ try
+ {
+ XMLPlatformUtils::Initialize();
+ sg_xml_init = true;
+
+ XMLTransService::Codes ret;
+ sg_coder = XMLPlatformUtils::fgTransService->makeNewTranscoderFor(sg_label_UTF_8, ret, sg_coder_buf_len);
+
+ if ( ret != XMLTransService::Ok )
+ {
+ const char* message = "Undefined Error";
+
+ switch ( ret )
+ {
+ case XMLTransService::UnsupportedEncoding: message = "Unsupported encoding"; break;
+ case XMLTransService::InternalFailure: message = "Internal failure"; break;
+ case XMLTransService::SupportFilesNotFound: message = "Support files not found"; break;
+ }
+
+ DefaultLogSink().Error("Xerces transform initialization error: %s\n", message);
+ }
+ }
+ catch (const XMLException &e)
+ {
+ DefaultLogSink().Error("Xerces initialization error: %s\n", e.getMessage());
+ }
+ }
+ }
}
+//
+bool
+kumu_XercesString_to_UTF_8(const std::basic_string<XMLCh>& in_str, std::string& out_str) {
+ return kumu_XercesString_to_UTF_8_p(in_str.c_str(), out_str);
+}
//
bool
-Kumu::StringIsXML(const char* document, ui32_t len)
+kumu_XercesString_to_UTF_8_p(const XMLCh* in_str, std::string& out_str)
{
- if ( document == 0 )
- return false;
+ assert(in_str);
+ assert(sg_xml_init);
+ AutoMutex AL(sg_coder_lock);
+ ui32_t str_len = XMLString::stringLen(in_str);
+ ui32_t read_total = 0;
+
+ try
+ {
+ while ( str_len > 0 )
+ {
+#if XERCES_VERSION_MAJOR < 3
+ ui32_t read_count = 0;
+#else
+ XMLSize_t read_count = 0;
+#endif
+ ui32_t write_count = sg_coder->transcodeTo(in_str + read_total, str_len,
+ (XMLByte*)sg_coder_buf, sg_coder_buf_len,
+ read_count, XMLTranscoder::UnRep_Throw);
+
+ out_str.append(sg_coder_buf, write_count);
+ str_len -= read_count;
+ read_total += read_count;
+ assert(str_len >= 0);
+ }
+ }
+ catch (...)
+ {
+ return false;
+ }
- if ( len == 0 )
- len = strlen(document);
+ return true;
+}
- XML_Parser Parser = XML_ParserCreate("UTF-8");
+//
+bool
+kumu_UTF_8_to_XercesString(const std::string& in_str, std::basic_string<XMLCh>& out_str) {
+ return kumu_UTF_8_to_XercesString_p(in_str.c_str(), out_str);
+}
- if ( Parser == 0 )
+//
+bool
+kumu_UTF_8_to_XercesString_p(const char* in_str, std::basic_string<XMLCh>& out_str)
+{
+ assert(in_str);
+ assert(sg_xml_init);
+ AutoMutex AL(sg_coder_lock);
+ ui32_t str_len = strlen(in_str);
+ ui32_t read_total = 0;
+
+ try
+ {
+ while ( str_len > 0 )
+ {
+#if XERCES_VERSION_MAJOR < 3
+ ui32_t read_count = 0;
+#else
+ XMLSize_t read_count = 0;
+#endif
+ ui32_t write_count = sg_coder->transcodeFrom((const XMLByte*)(in_str + read_total), str_len,
+ (XMLCh*)sg_coder_buf, sg_coder_buf_len / sizeof(XMLCh),
+ read_count, sg_coder_counts);
+
+ out_str.append((XMLCh*)sg_coder_buf, write_count * sizeof(XMLCh));
+ str_len -= read_count;
+ read_total += read_count;
+ assert(str_len >= 0);
+ }
+ }
+ catch (...)
{
- DefaultLogSink().Error("Error allocating memory for XML parser.\n");
return false;
}
- xph_test_wrapper Wrapper(Parser);
- XML_SetUserData(Parser, (void*)&Wrapper);
- XML_SetStartElementHandler(Parser, xph_test_start);
+ return true;
+}
- XML_Parse(Parser, document, len, 1);
- XML_ParserFree(Parser);
- return Wrapper.Status;
+//
+class MyTreeHandler : public HandlerBase
+{
+ ns_map* m_Namespaces;
+ std::stack<XMLElement*> m_Scope;
+ XMLElement* m_Root;
+ bool m_HasEncodeErrors;
+
+public:
+ MyTreeHandler(XMLElement* root) : m_Namespaces(0), m_Root(root), m_HasEncodeErrors(false)
+ {
+ assert(m_Root);
+ m_Namespaces = new ns_map;
+ }
+
+ ~MyTreeHandler() {
+ delete m_Namespaces;
+ }
+
+ bool HasEncodeErrors() const { return m_HasEncodeErrors; }
+
+ ns_map* TakeNamespaceMap()
+ {
+ if ( m_Namespaces == 0 || m_Namespaces->empty() )
+ return 0;
+
+ ns_map* ret = m_Namespaces;
+ m_Namespaces = 0;
+ return ret;
+ }
+
+ //
+ void AddNamespace(const char* ns_prefix, const char* ns_name)
+ {
+ assert(ns_prefix);
+ assert(ns_name);
+
+ if ( ns_prefix[0] == ':' )
+ {
+ ns_prefix++;
+ }
+ else
+ {
+ assert(ns_prefix[0] == 0);
+ ns_prefix = "";
+ }
+
+ ns_map::iterator ni = m_Namespaces->find(ns_prefix);
+
+ if ( ni != m_Namespaces->end() )
+ {
+ if ( ni->second->Name() != std::string(ns_name) )
+ {
+ DefaultLogSink().Error("Duplicate prefix: %s\n", ns_prefix);
+ return;
+ }
+ }
+ else
+ {
+ XMLNamespace* Namespace = new XMLNamespace(ns_prefix, ns_name);
+ m_Namespaces->insert(ns_map::value_type(ns_prefix, Namespace));
+ }
+
+ assert(!m_Namespaces->empty());
+ }
+
+ //
+ void startElement(const XMLCh* const x_name,
+ XERCES_CPP_NAMESPACE::AttributeList& attributes)
+ {
+ assert(x_name);
+ std::string tx_name;
+
+ if ( ! kumu_XercesString_to_UTF_8(x_name, tx_name) )
+ m_HasEncodeErrors = true;
+
+ const char* name = tx_name.c_str();
+ XMLElement* Element;
+ const char* ns_root = name;
+ const char* local_name = strchr(name, ':');
+
+ if ( local_name != 0 )
+ name = local_name + 1;
+
+ if ( m_Scope.empty() )
+ {
+ m_Scope.push(m_Root);
+ }
+ else
+ {
+ Element = m_Scope.top();
+ m_Scope.push(Element->AddChild(name));
+ }
+
+ Element = m_Scope.top();
+ Element->SetName(name);
+
+ // set attributes
+ ui32_t a_len = attributes.getLength();
+
+ for ( ui32_t i = 0; i < a_len; i++)
+ {
+ std::string aname, value;
+ if ( ! kumu_XercesString_to_UTF_8(attributes.getName(i), aname) )
+ m_HasEncodeErrors = true;
+
+ if ( ! kumu_XercesString_to_UTF_8(attributes.getValue(i), value) )
+ m_HasEncodeErrors = true;
+
+ const char* x_aname = aname.c_str();
+ const char* x_value = value.c_str();
+
+ if ( strncmp(x_aname, "xmlns", 5) == 0 )
+ AddNamespace(x_aname+5, x_value);
+
+ if ( ( local_name = strchr(x_aname, ':') ) == 0 )
+ local_name = x_aname;
+ else
+ local_name++;
+
+ Element->SetAttr(local_name, x_value);
+ }
+
+ // map the namespace
+ std::string key;
+ if ( ns_root != name )
+ key.assign(ns_root, name - ns_root - 1);
+
+ ns_map::iterator ni = m_Namespaces->find(key);
+ if ( ni != m_Namespaces->end() )
+ Element->SetNamespace(ni->second);
+ }
+
+ void endElement(const XMLCh *const name) {
+ 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 ( ! kumu_XercesString_to_UTF_8(chars, tmp) )
+ m_HasEncodeErrors = true;
+
+ m_Scope.top()->AppendBody(tmp);
+ }
+ }
+};
+
+//
+bool
+Kumu::XMLElement::ParseString(const char* document, ui32_t doc_len)
+{
+ if ( doc_len == 0 )
+ {
+ return false;
+ }
+
+ kumu_init_xml_dom();
+
+ int errorCount = 0;
+ SAXParser* parser = new SAXParser();
+
+ parser->setValidationScheme(SAXParser::Val_Always);
+ parser->setDoNamespaces(true); // optional
+
+ MyTreeHandler* docHandler = new MyTreeHandler(this);
+ parser->setDocumentHandler(docHandler);
+ parser->setErrorHandler(docHandler);
+
+ try
+ {
+ MemBufInputSource xmlSource(reinterpret_cast<const XMLByte*>(document),
+ static_cast<const unsigned int>(doc_len),
+ "pidc_rules_file");
+
+ parser->parse(xmlSource);
+ }
+ catch (const XMLException& e)
+ {
+ char* message = XMLString::transcode(e.getMessage());
+ DefaultLogSink().Error("Parser error: %s\n", message);
+ XMLString::release(&message);
+ errorCount++;
+ }
+ catch (const SAXParseException& e)
+ {
+ char* message = XMLString::transcode(e.getMessage());
+ DefaultLogSink().Error("Parser error: %s at line %d\n", message, e.getLineNumber());
+ XMLString::release(&message);
+ errorCount++;
+ }
+ catch (...)
+ {
+ DefaultLogSink().Error("Unexpected XML parser error\n");
+ errorCount++;
+ }
+
+ if ( errorCount == 0 )
+ m_NamespaceOwner = (void*)docHandler->TakeNamespaceMap();
+
+ delete parser;
+ delete docHandler;
+
+ return errorCount > 0 ? false : true;
+}
+
+//
+bool
+Kumu::XMLElement::ParseFirstFromString(const char* document, ui32_t doc_len)
+{
+ if ( doc_len == 0 )
+ {
+ return false;
+ }
+
+ kumu_init_xml_dom();
+
+ int errorCount = 0;
+ SAXParser* parser = new SAXParser();
+
+ parser->setValidationScheme(SAXParser::Val_Always);
+ parser->setDoNamespaces(true); // optional
+
+ MyTreeHandler* docHandler = new MyTreeHandler(this);
+ parser->setDocumentHandler(docHandler);
+ parser->setErrorHandler(docHandler);
+ XMLPScanToken token;
+
+ try
+ {
+ MemBufInputSource xmlSource(reinterpret_cast<const XMLByte*>(document),
+ static_cast<const unsigned int>(doc_len),
+ "pidc_rules_file");
+
+ if ( ! parser->parseFirst(xmlSource, token) )
+ {
+ ++errorCount;
+ }
+
+ if ( ! parser->parseNext(token) )
+ {
+ ++errorCount;
+ }
+ }
+ catch (...)
+ {
+ errorCount++;
+ }
+
+ if ( errorCount == 0 )
+ {
+ m_NamespaceOwner = (void*)docHandler->TakeNamespaceMap();
+ }
+
+ delete parser;
+ delete docHandler;
+
+ return errorCount > 0 ? false : true;
}
-#else // no XML parser support
+
+#endif
+
+//----------------------------------------------------------------------------------------------------
+
+#if ! defined(HAVE_EXPAT) && ! defined(HAVE_XERCES_C)
//
bool
-Kumu::XMLElement::ParseString(const std::string& document)
+Kumu::XMLElement::ParseString(const char* document, ui32_t doc_len)
{
- DefaultLogSink().Error("asdcplib compiled without XML parser support.\n");
+ 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* document, ui32_t doc_len)
{
DefaultLogSink().Error("Kumu compiled without XML parser support.\n");
return false;
#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
//