2#include <xercesc/parsers/XercesDOMParser.hpp>
3#include <xercesc/util/BinInputStream.hpp>
4#include <xercesc/sax/InputSource.hpp>
12class IStreamInputSource :
public xercesc::InputSource {
15 xercesc::BinInputStream* makeStream()
const {
16 return new IStreamBinInputStream(is);
19 class IStreamBinInputStream :
public xercesc::BinInputStream {
22 IStreamBinInputStream(std::istream &is) : xercesc::BinInputStream(), is(is) {};
23 XMLFilePos curPos(
void)
const {
return (XMLFilePos)is.tellg(); };
24 XMLSize_t readBytes(XMLByte*
const buf,
const XMLSize_t max) {
25 is.read((
char*)buf, (std::streamsize)max);
26 return (XMLSize_t)is.gcount();
28 const XMLCh* getContentType()
const {
34 IStreamInputSource(std::istream &is) : InputSource(), is(is) {};
38 char* cStr = xercesc::XMLString::transcode(xmlChStr);
40 throw std::runtime_error(
"Failed to transcode XML string");
42 std::string result(cStr);
43 xercesc::XMLString::release(&cStr);
49 xercesc::XMLPlatformUtils::Initialize();
50 std::unique_ptr<xercesc::XercesDOMParser> parser = std::make_unique<xercesc::XercesDOMParser>();
51 parser->setDoNamespaces(
true);
52 parser->parse(IStreamInputSource(xmlStream));
54 xercesc::DOMDocument* document = parser->getDocument();
57 xercesc::XMLPlatformUtils::Terminate();
58 throw std::runtime_error(
"Failed to parse XML stream");
61 xercesc::DOMElement* rootElement = document->getDocumentElement();
64 xercesc::XMLPlatformUtils::Terminate();
65 throw std::runtime_error(
"Failed to get root element of XML stream");
68 std::string rootName =
transcode(rootElement->getLocalName());
71 xercesc::XMLPlatformUtils::Terminate();
77 std::istringstream iss(xmlString);
83 const std::filesystem::path filePath(filename);
84 if (!std::filesystem::exists(filePath)) {
85 throw std::runtime_error(
"XML file '" + std::filesystem::absolute(filePath).
string() +
"' not found");
88 xercesc::XMLPlatformUtils::Initialize();
89 std::unique_ptr<xercesc::XercesDOMParser> parser = std::make_unique<xercesc::XercesDOMParser>();
90 parser->setDoNamespaces(
true);
91 XMLCh* xmlFilename = xercesc::XMLString::transcode(filename.c_str());
92 parser->parse(xmlFilename);
93 xercesc::XMLString::release(&xmlFilename);
96 xercesc::DOMDocument* document = parser->getDocument();
99 xercesc::XMLPlatformUtils::Terminate();
100 throw std::runtime_error(
"Failed to load and parse XML file: " + filename);
103 xercesc::DOMElement* rootElement = document->getDocumentElement();
106 xercesc::XMLPlatformUtils::Terminate();
107 throw std::runtime_error(
"Failed to get root element of XML file: " + filename);
110 std::string rootName =
transcode(rootElement->getLocalName());
114 xercesc::XMLPlatformUtils::Terminate();
126 return createInstance<XMLObject>(
xmlns,
"XMLObject", element);
135 xercesc::DOMNamedNodeMap* elementAttributes = element->getAttributes();
136 for (XMLSize_t i = 0; i < elementAttributes->getLength(); i++) {
137 xercesc::DOMNode* item = elementAttributes->item(i);
144 attributes.push_back( { attributeXmlns, attributePrefix, attributeName, attributeValue } );
148 for (
auto& defaultAttribute : defaultAttributes ) {
155 for (xercesc::DOMElement *childElement = element->getFirstElementChild(); childElement; childElement = childElement->getNextElementSibling()) {
167 if ( child->elementName == name ) {
171 throw std::runtime_error(
"Failed to get required child '" + name +
"' of element '" +
elementName +
"'");
184 std::vector< std::reference_wrapper<XMLObject> > result;
186 if ( child->elementName == name ) {
187 result.push_back(*child);
195 [name](
Attribute& attribute) { return attribute.name == name; }
200 throw std::runtime_error(
"Failed to get required attribute '" + name +
"' of element '" +
elementName +
"'");
205 [name](
Attribute& attribute) { return attribute.name == name; }
216 xmlString += std::string(
" ") + (!attribute.prefix.empty() ? attribute.prefix +
":" :
"") + attribute.name +
"=\"" + attribute.value.value +
"\"";
221 xmlString += child->stringify();
230 auto indent = [&indentation](
unsigned int n) -> std::string {
232 for (
unsigned int i = 0; i < n; ++i) {
233 result += indentation;
238 std::string xmlString = indent(depth) + std::string(
"<") + (!
prefix.empty() ?
prefix +
":" :
"") +
elementName;
240 xmlString += std::string(
" ") + (!attribute.prefix.empty() ? attribute.prefix +
":" :
"") + attribute.name +
"=\"" + attribute.value.value +
"\"";
245 xmlString += child->format(indentation, depth+1);
A class representing a node in an XML-tree.
static XMLObject * createFromFile(const std::string &filename)
Create an XMLObject from an XML file.
static XMLObject * createFromString(const std::string &xmlString)
Create an XMLObject from a string representation of XML.
static XMLObject * createObject(const xercesc::DOMElement *element)
std::optional< std::reference_wrapper< XMLObject > > getOptionalChildByName(const ElementName &name)
Get the optional child with the specified element name.
std::string format(std::string indentation="\t", unsigned int depth=0) const
Creates formatted string representing the XMLObject including its children.
std::optional< std::reference_wrapper< Attribute > > getOptionalAttributeByName(const AttributeName &name)
Get an optional attribute with the specified attribute name.
Children children
Child nodes of the XML element.
XMLObject & getRequiredChildByName(const ElementName &name)
Get a required child with the specified element name.
TextContent textContent
Textual content of XML element without children.
std::string stringify() const
Convert the XMLObject and its children to a string representation.
XMLObject(const Namespace &xmlns, const ClassName &className, const xercesc::DOMElement *element, const Attributes &defaultAttributes)
Attribute & getRequiredAttributeByName(const AttributeName &name)
Get a required attribute with the specified attribute name.
static XMLObject * createFromStream(std::istream &xmlStream)
Create an XMLObject from the input stream.
std::vector< std::reference_wrapper< XMLObject > > getChildrenByName(const ElementName &name)
Get all children with the specified element name.
The XML namespace contains classes representing XML-nodes defined in given XML-schema(s).
std::ostream & operator<<(std::ostream &os, const XMLObject *obj)
Allows printing of stringified XML object.
std::vector< Attribute > Attributes
std::string AttributeName
std::string transcode(const XMLCh *xmlChStr)
A struct representing an attribute of an XML-node.
A struct representing the value of an XML-node attribute.