FERS 1.0.0
The Flexible Extensible Radar Simulator
Loading...
Searching...
No Matches
XmlDocument Class Reference

Class for managing XML documents. More...

#include "libxml_wrapper.h"

Public Member Functions

 XmlDocument ()
 Constructor for XmlDocument.
 
 ~XmlDocument ()=default
 
 XmlDocument (const XmlDocument &)=delete
 
 XmlDocument (XmlDocument &&) noexcept=default
 
XmlDocumentoperator= (const XmlDocument &)=delete
 
XmlDocumentoperator= (XmlDocument &&) noexcept=default
 
bool loadFile (std::string_view filename)
 Load an XML file into the document.
 
bool loadString (const std::string &content)
 Load an XML document from a string in memory.
 
bool saveFile (const std::string_view filename) const
 Save the document to a file.
 
std::string dumpToString () const
 Dumps the document to a string.
 
void setRootElement (const XmlElement &root) const
 Set the root element of the document.
 
XmlElement getRootElement () const
 Get the root element of the document.
 
bool validateWithDtd (std::span< const unsigned char > dtdData) const
 Validate the document using a DTD.
 
bool validateWithXsd (std::span< const unsigned char > xsdData) const
 Validate the document using an XSD schema.
 

Detailed Description

Class for managing XML documents.

Definition at line 227 of file libxml_wrapper.h.

Constructor & Destructor Documentation

◆ XmlDocument() [1/3]

XmlDocument::XmlDocument ( )

Constructor for XmlDocument.

Exceptions
std::runtime_errorif the document creation fails.

Definition at line 237 of file libxml_wrapper.h.

237 : _doc(xmlNewDoc(reinterpret_cast<const xmlChar*>("1.0")), &xmlFreeDoc)
238 {
239 if (!_doc)
240 {
241 throw XmlException("Failed to create XML document.");
242 }
243 }
Exception class for handling XML-related errors.

◆ ~XmlDocument()

XmlDocument::~XmlDocument ( )
default

◆ XmlDocument() [2/3]

XmlDocument::XmlDocument ( const XmlDocument )
delete

◆ XmlDocument() [3/3]

XmlDocument::XmlDocument ( XmlDocument &&  )
defaultnoexcept

Member Function Documentation

◆ dumpToString()

std::string XmlDocument::dumpToString ( ) const

Dumps the document to a string.

Returns
A string containing the XML document.

Definition at line 248 of file libxml_wrapper.cpp.

249{
250 if (!_doc)
251 {
252 LOG(logging::Level::ERROR, "Document is null; Cannot dump to string");
253 return "";
254 }
255 xmlChar* buffer = nullptr;
256 int size = 0;
257 xmlDocDumpFormatMemory(_doc.get(), &buffer, &size, 1);
258 if (buffer == nullptr)
259 {
260 LOG(logging::Level::ERROR, "Failed to dump XML document to memory buffer.");
261 return "";
262 }
263 const std::string result(reinterpret_cast<const char*>(buffer), static_cast<size_t>(size));
264 xmlFree(buffer);
265 return result;
266}
#define LOG(level,...)
Definition logging.h:19
@ ERROR
Error level for error events.

References logging::ERROR, and LOG.

Referenced by serial::world_to_xml_string().

+ Here is the caller graph for this function:

◆ getRootElement()

XmlElement XmlDocument::getRootElement ( ) const

Get the root element of the document.

Returns
The root element.
Exceptions
std::runtime_errorif the document is not loaded or the root element is missing.

Definition at line 315 of file libxml_wrapper.h.

316 {
317 if (!_doc)
318 {
319 throw std::runtime_error("Document not loaded");
320 }
321 const xmlNode* root = xmlDocGetRootElement(_doc.get());
322 if (root == nullptr)
323 {
324 throw std::runtime_error("Root element not found");
325 }
326 return XmlElement(root);
327 }
Class representing a node in an XML document.

Referenced by serial::xml_parser_utils::collectIncludeElements(), radar::FileTarget::FileTarget(), mergeXmlDocuments(), serial::xml_parser_utils::processParsedDocument(), and removeIncludeElements().

+ Here is the caller graph for this function:

◆ loadFile()

bool XmlDocument::loadFile ( std::string_view  filename)

Load an XML file into the document.

Parameters
filenameThe name of the file to load.
Returns
True if the file was successfully loaded, otherwise false.

Definition at line 218 of file libxml_wrapper.cpp.

219{
220 xmlResetLastError();
221 // Pass NOERROR and NOWARNING to prevent default terminal spam, so we handle it cleanly
222 _doc.reset(xmlReadFile(filename.data(), nullptr, XML_PARSE_NOERROR | XML_PARSE_NOWARNING));
223 if (!_doc)
224 {
225 std::string fancyError =
226 formatError("XML Parsing Failed", getXmlLastErrorFormatted(), "Ensure the XML file is well-formed.");
227 LOG(logging::Level::ERROR, "{}", fancyError);
228 return false;
229 }
230 return true;
231}

References logging::ERROR, and LOG.

Referenced by serial::xml_parser_utils::addIncludeFilesToMainDocument(), serial::xml_parser_utils::collectIncludeElements(), radar::FileTarget::FileTarget(), and serial::parseSimulation().

+ Here is the caller graph for this function:

◆ loadString()

bool XmlDocument::loadString ( const std::string &  content)

Load an XML document from a string in memory.

Parameters
contentThe string containing the XML document.
Returns
True if the string was successfully parsed, otherwise false.

Definition at line 233 of file libxml_wrapper.cpp.

234{
235 xmlResetLastError();
236 _doc.reset(xmlReadMemory(content.c_str(), static_cast<int>(content.length()), "in_memory.xml", nullptr,
237 XML_PARSE_NOERROR | XML_PARSE_NOWARNING));
238 if (!_doc)
239 {
240 std::string fancyError =
241 formatError("XML Parsing Failed", getXmlLastErrorFormatted(), "Ensure the XML string is well-formed.");
242 LOG(logging::Level::ERROR, "{}", fancyError);
243 return false;
244 }
245 return true;
246}

References logging::ERROR, and LOG.

Referenced by serial::parseSimulationFromString().

+ Here is the caller graph for this function:

◆ operator=() [1/2]

XmlDocument & XmlDocument::operator= ( const XmlDocument )
delete

◆ operator=() [2/2]

XmlDocument & XmlDocument::operator= ( XmlDocument &&  )
defaultnoexcept

◆ saveFile()

bool XmlDocument::saveFile ( const std::string_view  filename) const

Save the document to a file.

Parameters
filenameThe name of the file to save to.
Returns
True if the file was successfully saved, otherwise false.

Definition at line 277 of file libxml_wrapper.h.

278 {
279 if (!_doc)
280 {
281 LOG(logging::Level::ERROR, "Document is null; Cannot save to file");
282 return false;
283 }
284 return xmlSaveFormatFileEnc(filename.data(), _doc.get(), "UTF-8", 1) != -1;
285 }

References logging::ERROR, and LOG.

◆ setRootElement()

void XmlDocument::setRootElement ( const XmlElement root) const

Set the root element of the document.

Parameters
rootThe root element to set.
Exceptions
std::runtime_errorif the document is not created.

Definition at line 300 of file libxml_wrapper.h.

301 {
302 if (!_doc)
303 {
304 throw std::runtime_error("Document not created");
305 }
306 xmlDocSetRootElement(_doc.get(), root.getNode());
307 }
xmlNodePtr getNode() const noexcept
Get the underlying XML node pointer.

References XmlElement::getNode().

Referenced by serial::world_to_xml_string().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ validateWithDtd()

bool XmlDocument::validateWithDtd ( std::span< const unsigned char >  dtdData) const

Validate the document using a DTD.

Parameters
dtdDataThe DTD data used for validation.
Returns
True if the document is valid according to the DTD.
Exceptions
XmlExceptionif the DTD is invalid or the validation fails.

Definition at line 97 of file libxml_wrapper.cpp.

98{
99 xmlDtdPtr dtd =
100 xmlIOParseDTD(nullptr,
101 xmlParserInputBufferCreateMem(reinterpret_cast<const char*>(dtdData.data()),
102 static_cast<int>(dtdData.size()), XML_CHAR_ENCODING_UTF8),
103 XML_CHAR_ENCODING_UTF8);
104 if (dtd == nullptr)
105 {
106 throw XmlException("Failed to parse DTD from memory.");
107 }
108
109 const std::unique_ptr<xmlValidCtxt, decltype(&xmlFreeValidCtxt)> validation_ctxt(xmlNewValidCtxt(),
110 xmlFreeValidCtxt);
111 if (!validation_ctxt)
112 {
113 xmlFreeDtd(dtd);
114 throw XmlException("Failed to create validation context.");
115 }
116
117 // Bind our custom error handler into the DTD Validation Context
118 std::string dtdErrors;
119 validation_ctxt->userData = &dtdErrors;
120 validation_ctxt->error = libxmlGenericErrorCallback;
121 validation_ctxt->warning = libxmlGenericErrorCallback;
122
123 const bool is_valid = xmlValidateDtd(validation_ctxt.get(), _doc.get(), dtd) != 0;
124 xmlFreeDtd(dtd);
125
126 if (!is_valid)
127 {
128 std::string fancyError = formatError("XML DTD Validation Failed", dtdErrors,
129 "Check your scenario XML tags and attributes against 'fers-xml.dtd'.");
130 LOG(logging::Level::ERROR, "{}", fancyError);
131 throw XmlException("XML failed DTD validation.");
132 }
133
134 return true;
135}

References logging::ERROR, and LOG.

Referenced by serial::xml_parser_utils::validateXml().

+ Here is the caller graph for this function:

◆ validateWithXsd()

bool XmlDocument::validateWithXsd ( std::span< const unsigned char >  xsdData) const

Validate the document using an XSD schema.

Parameters
xsdDataThe XSD data used for validation.
Returns
True if the document is valid according to the XSD schema.
Exceptions
XmlExceptionif the XSD is invalid or the validation fails.

Definition at line 137 of file libxml_wrapper.cpp.

138{
139 const std::unique_ptr<xmlSchemaParserCtxt, decltype(&xmlSchemaFreeParserCtxt)> schema_parser_ctxt(
140 xmlSchemaNewMemParserCtxt(reinterpret_cast<const char*>(xsdData.data()), static_cast<int>(xsdData.size())),
141 xmlSchemaFreeParserCtxt);
142 if (!schema_parser_ctxt)
143 {
144 throw XmlException("Failed to create schema parser context.");
145 }
146
147 // Bind custom error handler into the Schema Parse Context
148 std::string xsdParseErrors;
149 xmlSchemaSetParserErrors(schema_parser_ctxt.get(), libxmlGenericErrorCallback, libxmlGenericErrorCallback,
150 &xsdParseErrors);
151
152 const std::unique_ptr<xmlSchema, decltype(&xmlSchemaFree)> schema(xmlSchemaParse(schema_parser_ctxt.get()),
153 xmlSchemaFree);
154 if (!schema)
155 {
156 std::string fancyError =
157 formatError("XSD Schema Parse Failed", xsdParseErrors, "The internal XSD schema is invalid.");
158 LOG(logging::Level::FATAL, "{}", fancyError);
159 throw XmlException("Failed to parse schema from memory.");
160 }
161
162 const std::unique_ptr<xmlSchemaValidCtxt, decltype(&xmlSchemaFreeValidCtxt)> schema_valid_ctxt(
163 xmlSchemaNewValidCtxt(schema.get()), xmlSchemaFreeValidCtxt);
164 if (!schema_valid_ctxt)
165 {
166 throw XmlException("Failed to create schema validation context.");
167 }
168
169 // Bind custom error handler into the Schema Validation Context
170 std::string xsdErrors;
171 xmlSchemaSetValidErrors(schema_valid_ctxt.get(), libxmlGenericErrorCallback, libxmlGenericErrorCallback,
172 &xsdErrors);
173
174 if (const bool is_valid = xmlSchemaValidateDoc(schema_valid_ctxt.get(), _doc.get()) == 0; !is_valid)
175 {
176 std::string fancyError = formatError("XML XSD Validation Failed", xsdErrors,
177 "Check your scenario XML tags and attributes against 'fers-xml.xsd'.");
178 LOG(logging::Level::ERROR, "{}", fancyError);
179 throw XmlException("XML failed XSD validation.");
180 }
181
182 return true;
183}
@ FATAL
Fatal level for severe error events.

References logging::ERROR, logging::FATAL, and LOG.

Referenced by serial::xml_parser_utils::validateXml().

+ Here is the caller graph for this function:

The documentation for this class was generated from the following files: