rapidxml - how do I create an array of xml_document(s)? - rapidxml

I have multiple documents to parse and I need access to all the document objects for the lifetime of the creating class. How do I create an array of xml_document pointers as a member variable?
I've tried creating a single member variable as follows:
private:
rapidxml::xml_document<> *m_pDoc; // doesn't compile
error: name followed by "::" must be a class or namespace name
I'm sure this is because the template class isn't well defined but I'm not sure how to properly define the pointer.

That compiles fine for me. The error message implies you've forgotten this, maybe?
#include "rapidxml.hpp"

Rapidxml references to the pointers of your vector buffer every time you pass an xml. So store both your buffers and also the xml_document<> docs.
Put the filepaths of your xml docs
char *XMLFilePaths[numXmlDocs] = {"../PersonDatasetA/xmlFile.xml","../PersonDatasetB/xmlFile.xml"};
Store both the buffers and also the xml documents into arrays
std::array<vector<char>,numXmlDocs> XMLDocBuffers;
std::array<xml_document<>,numXmlDocs> XMLDocs;
//For each xml doc, read and store it in an array
for(int i=0;i<numXmlDocs;i++){
//Parse each xml into the buffer array
char xmlFileName[100] ;
sprintf(xmlFileName,"%s",XMLFilePaths[i]);
ifstream theFile (xmlFileName);
vector<char> buffer((istreambuf_iterator<char>(theFile)), istreambuf_iterator<char>());
buffer.push_back('\0');
//Store the buffer
XMLDocBuffers[i] = buffer;
// Parse the buffer usingthe xml file parsing library into doc
XMLDocs[i].parse<0>(&(XMLDataset_StringDocs[i][0]));
xml_node<> *root_node; // Find the root node
root_node = (XMLDocs[i]).first_node(typesOfSamples);

Related

Reading a ByteArray from a FileSystem or a Jar in Kotlin

I am often developing applications in an IDE and then distributing them with an executable JAR. So I seek interoperability in regards to library functions. I have a partial solution using an InputStream to robustly read data from a file located in either a FileSystem or a Jar file, but I would like to make use of the robust Kotlin function Closable.use() to adapt to the error being thrown or not.
After some struggle I found this post that explains how compression inside the Jar file makes its access different than that from a FileSystem. In particular the nice Kotlin extension function File.readBytes() will not work for a file in a Jar. That is a shame because looking into the source of readBytes() there is a clever use of the use() function to handle the stream contingencies. It says...
closes it down correctly whether an exception is thrown or not.
Here is the partial solution which returns a ByteArray. These functions work the same whether running the application from within the IDE or from an executable Jar.
inline fun <reified T> getResourceAsStream(filename:String):InputStream {
//it is calling function's responsibility to close the stream
//force the first character to be a backslash that indicates root
val fnameWithPath= if (filename[0] != '/') "/$filename" else filename
//extract the stream if it exists
return T::class.java.getResourceAsStream(fnameWithPath)
}
inline fun <reified T> getResourceByteArray(filename:String):ByteArray {
//will open a stream, read bytes and then close stream
val stream= getResourceAsStream<T>(filename)
val byteArray = stream.readBytes()
stream.close()
return byteArray
}
You're almost there.  What you might have missed is that Kotlin already defines an extension method use() on the Closable interface, which InputStream implements.  So your second method can be rewritten as a one-liner:
inline fun <reified T> getResourceByteArray(filename: String)
= getResourceAsStream<T>(filename).use{ it.readBytes() }
I incorporated #gidds ' solution to make use of the Kotlin library function Closeable.use() as part of the operation to load the ByteArray from a resource file through an InputStream. I'm expecting the use() function to take care of closing the InputStream or otherwise dealing with errors thrown or not.
In the updated code, the calling Class provided as a reified type gives the context for which resources directory will contain the file. In a multi-project build, there may be several resources directories. It is the case I'm operating under with different projects requiring different input data.
inline fun <reified T> getResourceAsStream(filename:String):InputStream {
//it is calling function's responsibility to close the stream
//force the first character to be a backslash that indicates root
val fnameWithPath= if (filename[0] != '/') "/$filename" else filename
//extract the stream if it exists
return T::class.java.getResourceAsStream(fnameWithPath)
}
inline fun <reified T> getResourceByteArray(filename: String)
= getResourceAsStream<T>(filename).use{ it.readBytes() }
class ReadByteData() {
init{
val byteArray= getResourceByteArray<ReadByteData>("fileName")
}
}

Check if QVariant is convertible to other QVariant type

I receive data in JSON using a QJsonObject. I also have a QObject-based object holding properties, using Q_PROPERTY(...), for the keys in the JSON. Since Qt now has some more datatypes than JSON how can one check if they are convertible.
The datatypes used in the object typically are one of the following but not limited to
uint
double
QString
QDateTime
bool
The idea is to automatically call setProperty(...) on the QOject derived object for every key/value in the QJsonObject. Since this could fail due to malformed input in the JSON I have to check validity based on the QMetaProperty and QJsonObject/QVariantMap data.
Since this should run generic as a base class implementing manual checks for every datatype fails. I know there is QVariant::isConvertible<T>().
#include <QJsonObject>
#include <QVariant>
#include <QMetaObject>
#include <QMetaProperty>
class Test {
Q_GADGET
Q_PROPERTY(QString test)
QString m_test;
QJsonObject jo;
void call();
}
void Test::call()
{
jo.insert("test",QJsonValue(5));
// This will fail, since int is not convertible to QString implicitly
staticMetaObject->property(staticMetaObject->propertyOffset()).writeOnGadget(this,jo["test"].toVariant());
}
Since I am parsing the JSON before to check if every property would have a corresponding key in the JSON-Object I really like to catch these there already without changing my original object. Something like:
jo["test"].toVariant().canConvert<staticMetaObject->property(staticMetaObject->propertyOffset()).type()>()
Instead of using templated bool QVariant::canConvert<T>() one can use bool QVariant::canConvert(int targetTypeId).
QMetaProperty po = staticMetaObject->property(staticMetaObject->propertyOffset());
jo["test"].toVariant().canConvert(po.type());

Qt C++ vector of QFiles error

I have the following:
QString themePath(":/themes/");
std::vector<QString> resourcePaths;
resourcePaths.push_back(QString("html/details.html"));
std::vector<QFile> resources;
for (std::vector<QString>::iterator it = resourcePaths.begin(); it != resourcePaths.end(); ++it) {
QString path = QString("%1%2/%3").arg(themePath, THEME, *it);
QFile resource(path);
resources.push_back(resource);
}
gives me the following error:
error: 'QFile::QFile(const QFile&)' is private.
I get the same error if I use QList instead of std::vector.
Thank you for your attention.
The problem, is that you use QFile values in the container which implicitly perform copying of items with using the copy constructor which is private member function of QFile class. The compiler tells you that. To solve this you can try to simply store QFile pointers instead.

returning a JSON formatted file via WCF

We've seen a number of posts relating to JSON data returns via WCF, but they all cover the aspect of converting object to JSON and then returning that object converted to JSON via the magic of attributes.
We've got a number of preformatted JSON files that we want to return via an WCF service. Essentially all we need to do is read the files in (or a cached copy of of the file) and then return the data as a string . I think ... It seems wasteful to read in the JSON file, serialize it to an object then deserialize back to JSON.. Any help on this?
When using the WebHttpBinding, this is as simple as creating a WebGet annotated method with a Stream return type:
[WebGet]
public Stream GetFile(Int32 someId)
{
//your logic to lookup or create the file here.
//Open the file (a MemoryStream would be acceptible as well if you were creating the data on the fly
Stream stream = File.OpenRead(yourFilePath);
//register an event to clean up the temporary file (if necessary)
OperationContext.Current.OperationCompleted += (s, e) =>
{
File.Delete(yourFilePath);
};
return stream;
}

how to refactor code inside curly braces in flex

Data binding in ActionScript is really cool. But what if I want to refactor a big switch or if statement inside the curly braces into a function, for example:
{person.gender == 'male' ? 'Mr.' : 'Ms.'}
into:
{salutation(person)}
The compiler doesn't let me do that. I know about properties and I could write getters and setters on the person object. But since I am using inlined JSON objects now that's not convenient(I think). What are other good ways to refactor this code?
To answer Matt's comment. The data type of person is just plain Object. It was decoded from JSON format coming from a service call.
You'll need to make the Person class (assuming you have one) bindable in order for this to work.
However, since you are saying you're using JSON objects, I'm assuming you just have anonymous objects that were parsed from a JSON string. In that case, I'm pretty sure that won't work. You'll need to create a strongly typed object that has bindable properties.
Just FYI: to avoid having to write custom JSON parsers for every object you want to create, you can create strong typed objects from vanilla objects using a bytearray trick:
public static function toInstance( object:Object, clazz:Class ):* {
var bytes:ByteArray = new ByteArray();
bytes.objectEncoding = ObjectEncoding.AMF0;
// Find the objects and byetArray.writeObject them, adding in the
// class configuration variable name -- essentially, we're constructing
// and AMF packet here that contains the class information so that
// we can simplly byteArray.readObject the sucker for the translation
// Write out the bytes of the original object
var objBytes:ByteArray = new ByteArray();
objBytes.objectEncoding = ObjectEncoding.AMF0;
objBytes.writeObject( object );
// Register all of the classes so they can be decoded via AMF
var typeInfo:XML = describeType( clazz );
var fullyQualifiedName:String = typeInfo.#name.toString().replace( /::/, "." );
registerClassAlias( fullyQualifiedName, clazz );
// Write the new object information starting with the class information
var len:int = fullyQualifiedName.length;
bytes.writeByte( 0x10 ); // 0x10 is AMF0 for "typed object (class instance)"
bytes.writeUTF( fullyQualifiedName );
// After the class name is set up, write the rest of the object
bytes.writeBytes( objBytes, 1 );
// Read in the object with the class property added and return that
bytes.position = 0;
// This generates some ReferenceErrors of the object being passed in
// has properties that aren't in the class instance, and generates TypeErrors
// when property values cannot be converted to correct values (such as false
// being the value, when it needs to be a Date instead). However, these
// errors are not thrown at runtime (and only appear in trace ouput when
// debugging), so a try/catch block isn't necessary. I'm not sure if this
// classifies as a bug or not... but I wanted to explain why if you debug
// you might seem some TypeError or ReferenceError items appear.
var result:* = bytes.readObject();
return result;
}

Resources