I'm writing a library which takes xml files and parses them. To prevent users from feeding inalid xmls into my application i'm using xerces to validate the xml files via an xsd.
However, i only manages to validate against xsd-files. Theoretically an user could just open this file and mess around with it. That's why i would like my xsd to be hardcoded in my library.
Unfortunately i haven't found a way to do this with XercesC++, yet.
That's how it is working right now...
bool XmlParser::validateXml(std::string a_XsdFilename)
{
xercesc::XercesDOMParser domParser;
if (domParser.loadGrammar(a_XsdFilename.c_str(), xercesc::Grammar::SchemaGrammarType) == NULL)
{
throw Exceptions::Parser::XmlSchemaNotReadableException();
}
XercesParserErrorHandler parserErrorHandler;
domParser.setErrorHandler(&parserErrorHandler);
domParser.setValidationScheme(xercesc::XercesDOMParser::Val_Always);
domParser.setDoNamespaces(true);
domParser.setDoSchema(true);
domParser.setValidationSchemaFullChecking(true);
domParser.parse(m_Filename.c_str());
return (domParser.getErrorCount() == 0);
}
std::string m_Filename is a member variable holding the path of the xml i validate.
std::string a_XsdFilename is the path to the xsd i validate against.
XercesParserErrorHandler inherits from xercesc::ErrorHandler and does error handling.
How can i replace std::string a_XsdFilename with something like std::string a_XsdText?
Where std::string a_XsdText contains the schema definition itself instead of a path to a file containing the schema definition.
I'll describe three ways of how to hardcode your XSD in your program:
by loading the XSD from a file path (this is what your example program does right now)
by loading the XSD from a string (this is what you ask for)
by loading the XSD from a precompiled binary
Loading the XSD from a file path
Boris Kolpackov suggests in a blog post that applications should provide the XSD schema files by themselves rather than looking up the schema files through the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attributes found in the XML file.
In the blog post there is a link to load-grammar-dom , an example program (put in the public domain) that makes use of the xercesc::DOMLSParser::loadGrammar function:
user#linux:~$ load-grammar-dom
usage: load-grammar-dom [test.xsd ... ] [test.xml ...]
user#linux:~$
Loading the XSD from a string
If you would like to pass the XSD file contents as a string, you would need to use another overload of
xercesc::DOMLSParser::loadGrammar
where you pass
const DOMLSInput *source
instead of
const char *const systemId
The DOMLSInput could be created with the help of xercesc::MemBufInputSource and xercesc::Wrapper4InputSource like this
xercesc::Wrapper4InputSource source(
new xercesc::MemBufInputSource(
(const XMLByte *) (a_XsdText.c_str()),
a_XsdText.size(),
"A name");
(Adapted somewhat from
https://stackoverflow.com/a/15829424/757777 but untested)
Loading the XSD from a precompiled binary
Included in the software CodeSynthesis XSD the embedded example (that is put in the public domain) demonstrates how to use
xercesc::BinInputStream and
xercesc::XMLGrammarPool::deserializeGrammars
to load a precompiled XSD schema.
See also README.
The example contains the program xsdbin that compiles XSD schema files into a binary file.
user#linux:~$ xsdbin --help
Usage: xsdbin [options] <files>
Options:
--help Print usage information and exit.
--verbose Print progress information.
--output-dir <dir> Write generated files to <dir>.
--hxx-suffix <sfx> Header file suffix instead of '-schema.hxx'.
--cxx-suffix <sfx> Source file suffix instead of '-schema.cxx'.
--array-name <name> Binary data array name.
--disable-multi-import Disable multiple import support.
user#linux:~$
In the makefile the XSD schema file is precompiled by xsdbin and the result ends up inside the example executable.
Related
UPDATE: After doing some more poking around, it looks as though the problem has to do with where CF is looking for the DTD file referenced in the XML.
We have the DTDs, but it looks as though CF isn't finding them, so it isn't sure how to parse the XML according to the DTD. I determined this by having it parse XML without any DTD, and it worked as expected and as I wanted - returning a parsed xmlDoc, not a string.
Is there some way of setting the default directory for where CF should look for the DTD specified in the XML?
We're running CF2021, and xmlParse(file), which should return a parsed XML object is instead returning the file contents as a string, inside a wddx encoded object. We have just migrated from a CF2018 server running on a remote hosting service to CF2021 running on an AWS box.
In order to return the XML object we need, I need to run xmlParse on the file, then wddx2cfml on the object, then xmlParse again on the string.
Is there a reason why xmlParse, which should return a parsed XML object, is instead behaving this way?
We pass the system file location to the method. Call it docPath, and it'd look something like g:\appName\xmlFiles\20230125.xml
Then we have, in cfscript:
doc = xmlParse(docPath);
When I dump that to a file, I get what I described above. When I change it to the following, I get what want:
docFile = xmlParse(docPath); cfwddx(action="wddx2cfml", input="#docFile#", output="xmlString"); xmlDoc = xmlParse(xmlString);
But I don't understand why this is necessary, and I'm concerned about having to change it everywhere in the code that we use xmlParse. For the record, this also occurs in tagged CF as well as cfscript, so it's not that.
Putting the dtd files in CF's WEB-INF folder solved the problem. CF was able to match the DTD with the DOCTYPE and properly parse the XML.
I have question about my internship project. They want me to create a basic Login page(ID, Password). I create a XML file for Username and Password. The program should check the XML file for username and password*. If they are correct it will direct to a second window. I'm stuck on processing XML file for username and password. How can read those information in XML file.
As #JarMan said, I would recommend the QXmlStreamReader. You can fill it with a file (QIODevice), QString, QByteArray, etc...
Parsing a value could e.g. look like that
xml.attributes().value( attribute ).toString();
if attribute is a QString and xml is the QXmlStreamReader.
See the doc https://doc.qt.io/qt-5/qxmlstreamreader.html
There are several ways to do it. Marris mentioned one, but another one is to have this kind of code generated automatically. The way this works is that you first write an XML Schema that describes what your XML data looks like. An introduction to the XML Schema language can be found e. g. here.
Then you use an XML Schema compiler to translate the XML Schema to C++ classes. The schema compiler will also generate code to parse an XML file into objects, meaning you don't have to write any code to deal with XML by hand. It's a purely declarative approach: declare what the data looks like, and let the computer figure out the details.
I want to use MDC to set a context in my program, and then be able to set a filter in the config file to only show messages from a logger in a certain context.
MDC mdc;
mdc.put("fieldName", "foo");
LOG4CPLUS_DEBUG(log, "ABC");
mdc.put("fieldName", "bar");
LOG4CPLUS_DEBUG(log, "XYZ");
I only want to print from log when "fieldName" is "bar", so only "XYZ" should be printed to my log.
In log4j this can be done using the XML format config file with filters. Can log4cplus use an XML config file? Can filters like this be set up in the XML log?
Also, is there a way to make log4cplus verbose, so I can see if it is finding my config file, and if it is able to read it, etc.
I am having trouble finding even one example of a log4cplus XML config file or how to read one.
Log4cplus does not support any kind of XML configuration file. This is because it would require an XML parser and that is a pretty heavy dependency.
As for the filtering using MDC, there is currently no such filter. You would have to implement your own. See the Filter class.
You can set up log4cplus debugging from property file using log4cplus.configDebug=1. Or you can set the LOG4CPLUS_LOGLOG_DEBUGENABLED environment variable to 1. The former takes precedence over the latter.
I'm writing a C/C++ Header file parser that converts .h files into a specific XML format.
I have a structure defined as follows:
struct struct1
{
struct structchild1
{
float child2;
} child3;
unsigned int child3;
};
I want the above structure to be represented as:
<tag1= "struct1">
<name>struct1</name>
<input_type>byte</input_type>
<method></method>
<tag_ref = "structchild1">
<name>child3</name>
<tag2 = "child2">
<name>child2<name>
<size>4<size>
</tag2>
</tag_ref>
<tag2= "child3">
<name>child3</name>
<len>4</len>
<value> </value>
</tag2>
</tag1>
My approach: I'm using a 2 stage process, I first convert the header file into a gccXML format and then use xerces-C++ for visual studio to print the results out into the XML file. I'm successfully able to parse everything (enums, typedefs etc) except nested structures or unions. Can somebpdy please help me out as to how to go about doing this? Thanks!
I dont know if this would help since you are using C++.But if you want to get this done easily you could go for JDOM or JAXB Parser in Java.The JAXB marshaller creates XML while the JAXB unmarshaller parses the XML.I have used JDOMparser to parse an XML including the CDATA section and it works brilliantly.Hope this helps.
May be you might want to have a look at this example.
http://www.mkyong.com/java/jaxb-hello-world-example/
The XML contains symbols that the C++ may misinterpret (like the // in http://www.w3.org/2000/10/XMLSchema)
I am wondering if you know about clean ways to include some hard-coded XML into a std::string or a CString, at compile time.
(in deed I'm trying to encode an .xsd file for validating some xml input, because I don't want to depend upon the presence or not of this xsd file, so I want it to be compiled in the binary)
const char* XML_STRING = "<?xml version=\"1.0\"?><Test></Test>";
std::string aTestXmlStr(XML_STRING);