Not able to parse through xmlReaderForMemory api - libxml2

My code generate the following string,
XmlWriter obj1;
obj1.StartDocWriting("MyObject.xml");
obj1.SetRootNode("Object");
obj1.CreateChildNodeToRootWithProperty("age","20");
obj1.CreateChildNodeToRootWithProperty("name","xyz");
obj1.xml_to_string(outbuf);
o/p xml string,
<?xml version="1.0"?>
<Object><age>20</age><name>xyz</name></Object>
when I am trying to parse it,i am getting the following error,
Entity: line 3: parser error : Extra content at the end of the
document
Here is my parsing code,
std:string inbuf = "<?xml version="1.0"?>
<Object><age>20</age><name>xyz</name></Object>"
XmlTextReader obj1;
xmlTextReaderPtr readPtr = obj1.parseBuffer(inbuf.c_str(),10000);
xmlTextReaderPtr XmlTextReader::parseBuffer( const char *aInBuffer,
int aInSize,
const char * aInUrl,
const char * aInEncoding,
int aInOptions )
{
xmlReader = xmlReaderForMemory( aInBuffer, aInSize, aInUrl, aInEncoding, aInOptions );
if( xmlReader == NULL )
{
printf("reader is null");
// LOG(LOG_INFO, "parseBuffer:: xmlReaderForMemory return NULL\n");
}
return xmlReader;
}

Related

snprintf is not working correct for special chars

I am trying to create a variable with using snprintf formatter but when I use some special chars inside string such as "!", I am getting this wrong value:
"Hi there, this is esp32!" => "⸮⸮?"
void sendMessage(String _channelName, String _username, String _messageText, String _messageType) {
Serial.println(_messageText); // writes correct => "Hi there, this is esp32!"
char messageData[500];
snprintf(messageData, sizeof(messageData),
"[\"SEND\\ndestination:/app/chat/%s\\n\\n{\\\"username\\\":\\\"%s\\\",\\\"message\\\":\\\"%s\\\",\\\"messageType\\\":\\\"%s\\\"}\\u0000\"]",
_channelName,
_username,
_messageText, // writes wrong => "⸮⸮?\"
_messageType);
String messageDataConverted = String(messageData);
Serial.println(messageDataConverted);
webSocket.sendTXT(messageDataConverted);
}
The function prototype of snprintf() looks like this:
int snprintf ( char * s, size_t n, const char * format, ... );
snprintft() doesn't expecting an Arduino String which is the type of your _username. You need to convert it from a String to a char * with _username.c_str().

How to set a enum property with QVariant(get value from xml text node) by QObject::setProperty in qt 5(any specific version)

Recently I want to reconstruct a object from xml file. a xml file looks like:
<?xml version="1.0" encoding="UTF-8"?>
<Root version="0.0.1" author="lee" modify="2020-10-03">
<ExampleOject>
<_id>10</_id>
<_openType>1</_openType>
</ExampleOject>
</Root>
The _openType in the xml is a property of ExampleOject and it's a enum:
class ExampleOject
{
Q_OBJECT
Q_PROPERTY(OpenType _openType READ getType WRITE setType)
public:
enum OpenType{BY_ID = 1, BY_NAME=2};
Q_ENUM(Status)
OpenType _openType;
OpenType getType() const{return _openType;}
void setType(const OpenType &type){_openType = type;}
};
After I find that property node and I read from file and set into property like:
QString propertyName = xmlReader.name().toString();
QString propertyValue = xmlReader.readElementText();
if(!obj->setProperty(propertyName.toStdString().c_str(), QVariant(propertyValue)))
{
return;
}
But this fails(QObject::setProperty returns false and ) and I looked around and one thing I get is that we can only set a enum type with int or uint, not from QString or any other.
Is there any way to set a enum property of a object in qt5 by QObject::setProperty or other method?
For now, I achieve this in two steps:
When writing a property into xml, write a attribute type="enum" if it is a enumerate property with QMetaProperty::isEnumType()
When reading a property, check if it has a attribute type="enum"
So, At last my xml file looks like:
<?xml version="1.0" encoding="UTF-8"?>
<Root version="0.0.1" author="lee" modify="2020-10-03">
<ExampleOject>
<_id>10</_id>
<_openType type="enum">1</_openType>
</ExampleOject>
</Root>
STEP 1. the related writing codes:
//... get _openType node
QMetaProperty metaproperty = staticMetaObject.property(i);
if(metaproperty.isEnumType())
{
// write type = "enum" attribute into that node
}
//...
STEP 2. reading:
// ... get _openType node
auto isEnum = xmlReader.attributes().value("type");
if(isEnum.toString() == QString("enum"))
{
QString propertyValue = xmlReader.readElementText();
qint32 enumValue = propertyValue.toInt();
if(!obj->setProperty(propertyName.toStdString().c_str(), QVariant(enumValue)))
{
return;
}
else
{
QString propertyValue = xmlReader.readElementText();
if(!obj->setProperty(propertyName.toStdString().c_str(), QVariant(propertyValue)))
{
return;
}
}
}
//...
Any other good ideas? This just works for me.

How to best work with serialization of TREX files in .NET core?

I'm looking at an XML Metadata Interchange (XMI) based document created by TreeAge. E.G. Here is the physical contents of a *.trex file:
<?xml version="1.0" encoding="ASCII"?>
<xmi:XMI xmi:version="2.0"
xmlns:xmi="http://www.omg.org/XMI"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:notation="http://www.eclipse.org/gmf/runtime/1.0.2/notation"
xmlns:tree="http://www.treeage.com/modeldefs/tree">
<tree:Tree xmi:id="_Uj1WYAR_EemNnJYeA_zjSg">
<Node xmi:id="_nem4Bx6OEemrY_k4als23a" NameID="Node10" Label="Tenth_Node_Name" NodeType="TerminalNode">
<Prob xmi:id="_nem4CB6OEemrY_k4bks23a" Value="Tenth_Node_Expression"/>
<MarkovData xsi:type="tree:MarkovJumpTransitionData" xmi:id="_nem4CR6OEemrY_k4bks23a" MarkovJumpState="Jump">
<Modification xmi:id="_nem4Ch6OEemrY_k4bks23a" Tracker="Tenth_Node_Tracker_1" Value="Tenth_Node_Tracker_1_Expression"/>
<Modification xmi:id="_nem4Cx6OEemrY_k4bks23a" Tracker="Tenth_Node_Tracker_2" Value="Tenth_Node_Tracker_2_Expression"/>
<Modification xmi:id="_nem4DB6OEemrY_k4bks23a" Tracker="Tenth_Node_Tracker_3" Value="Tenth_Node_Tracker_3_Expression"/>
<Modification xmi:id="_nem4DR6OEemrY_k4cjs23a" Tracker="Tenth_Node_Tracker_4" Value="Tenth_Node_Tracker_4_Expression"/>
</MarkovData>
</Node>
..// Bunches of XML data
enter code here
</tree:Tree>
</xmi:XMI>
UNIT TEST
I don't want hacks in the unit test. I wish TreeAgeXml was generated code, but I don't know how. How can I fix hacks? How can I generate the TreeAgeXml C# class?
public void ShouldBuildATree_Test()
{
string filePath = "Files/brianTest.trex";// Similar example above
string fileXml = System.IO.File.ReadAllText(filePath);
var treeAge = TrexUtil.BuildTreeFromXml(fileXml);
var serializedXml = TrexUtil.SerialzeTreeAgeToXml(treeAge);
serializedXml.ShouldBe(fileXml);
}
public static TreeAgeXml BuildTreeFromXml(string xml)
{
xml = xml.Replace("xsi:type", "xsitype"); // HACK
xml = xml.Replace("xsi:nil", "xsinil"); // HACK
var serializer = new XmlSerializer(typeof(XML.TreeAgeXml));
XML.TreeAgeXml treeage = null;
using (TextReader reader = new StringReader(xml))
{
treeage = (XML.TreeAgeXml)serializer.Deserialize(reader);
}
return treeage;
}
//TreeAgeXml is built out by hand over time through trial and error
public static string SerialzeTreeAgeToXml(TreeAgeXml treeAge)
{
XmlSerializer xs = new XmlSerializer(typeof(TreeAgeXml));
XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
ns.Add("xmi", "http://www.omg.org/XMI");
ns.Add("xsi", "http://www.w3.org/2001/XMLSchema-instance");
ns.Add("notation", "http://www.eclipse.org/gmf/runtime/1.0.2/notation");
ns.Add("tree", "http://www.treeage.com/modeldefs/tree");
string xml = "";
using(StringWriter textWriter = new StringWriter())
{
xs.Serialize(textWriter, treeAge, ns);
xml = textWriter.ToString();
}
// Hacks for things that didn't serialize quite right
xml = xml.Replace("xsitype", "xsi:type");
xml = xml.Replace("xsinil", "xsi:nil");
xml = xml.Replace(">", ">");
xml = xml.Replace("\" />", "\"/>");
xml = xml.Replace("\t", " ");
// Hacks Manually insert the first two lines, because they never come out right
var lines = xml.Split('\n');
lines[0] = "<?xml version=\"1.0\" encoding=\"ASCII\"?>";
lines[1] = "<xmi:XMI xmi:version=\"2.0\" xmlns:xmi=\"http://www.omg.org/XMI\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:notation=\"http://www.eclipse.org/gmf/runtime/1.0.2/notation\" xmlns:tree=\"http://www.treeage.com/modeldefs/tree\">";
xml = String.Join('\n', lines);
xml = xml + '\n';
return xml;
}

Flex: Read bytearray

I use the following to upload a file to Flex:
private var filer:FileReference;
protected function button1_clickHandler(event:MouseEvent):void
{
var fd:String = "Files (*)";
var fe:String = "*";
var ff:FileFilter = new FileFilter(fd, fe);
filer = new FileReference();
filer.addEventListener(Event.SELECT, onFileSelect);
filer.browse(new Array(ff));
filer.addEventListener(Event.COMPLETE,
function (e:Event):void {
e.currentTarget.data.toString();
}
);
}
private function onFileSelect(e:Event):void {
filer.load();
}
And my file looks like this:
Here is the original file: http://sesija.com/up/1.txt
I need to read the uploaded file and parse it. The problem is that in my e.currentTarget.data.toString(); I get only '1' and not the rest of the String.
Any idea on how to successfully read this entire txt file?
The data property is a ByteArray. Instead of using the toString method (which apparently treats NULL byte as end of string), use specific read methods of the ByteArray class like readByte, readInt etc.
var array:Array = [];
var ba:ByteArray = e.currentTarget.data as ByteArray;
while(ba.bytesAvailable != 0){
array.push(ba.readByte());
}
trace(array.join(", "));
You might want to read Working with byte arrays

Enumerate the properties of an AS3 object that may or may not be dynamic

In order to send a POST request I need to enumerate all properties of a given object. This object may or may not be dynamic. I'm looking for the most elegant solution. This is what I've got so far:
function createURLVariables(params:Object):URLVariables
{
// Workaround: Flash Player performs a GET if no params are passed
params ||= {forcePost: true};
var vars:URLVariables = new URLVariables();
var propertyName:String;
var propertyList:XMLList = describeType(params)..variable;
var propertyListLength:int = propertyList.length();
// A dynamic object won't return properties in this fashion
if (propertyListLength > 0)
{
for (var i:int; i < propertyListLength; i++)
{
propertyName = propertyList[i].#name;
vars[propertyName] = params[propertyName];
}
}
else
{
for (propertyName in params)
vars[propertyName] = params[propertyName];
}
return vars;
}
One potential problem is that this won't return properties for getters (accessors).
I took the following approach in the as3corelib JSON Encoder. You'll have to modify this to suit your needs, but it should give you an idea to work from. Note that there is some recursion in here (the convertToString call, which you might not need:
/**
* Converts an object to it's JSON string equivalent
*
* #param o The object to convert
* #return The JSON string representation of <code>o</code>
*/
private function objectToString( o:Object ):String
{
// create a string to store the object's jsonstring value
var s:String = "";
// determine if o is a class instance or a plain object
var classInfo:XML = describeType( o );
if ( classInfo.#name.toString() == "Object" )
{
// the value of o[key] in the loop below - store this
// as a variable so we don't have to keep looking up o[key]
// when testing for valid values to convert
var value:Object;
// loop over the keys in the object and add their converted
// values to the string
for ( var key:String in o )
{
// assign value to a variable for quick lookup
value = o[key];
// don't add function's to the JSON string
if ( value is Function )
{
// skip this key and try another
continue;
}
// when the length is 0 we're adding the first item so
// no comma is necessary
if ( s.length > 0 ) {
// we've already added an item, so add the comma separator
s += ","
}
s += escapeString( key ) + ":" + convertToString( value );
}
}
else // o is a class instance
{
// Loop over all of the variables and accessors in the class and
// serialize them along with their values.
for each ( var v:XML in classInfo..*.(
name() == "variable"
||
(
name() == "accessor"
// Issue #116 - Make sure accessors are readable
&& attribute( "access" ).charAt( 0 ) == "r" )
) )
{
// Issue #110 - If [Transient] metadata exists, then we should skip
if ( v.metadata && v.metadata.( #name == "Transient" ).length() > 0 )
{
continue;
}
// When the length is 0 we're adding the first item so
// no comma is necessary
if ( s.length > 0 ) {
// We've already added an item, so add the comma separator
s += ","
}
s += escapeString( v.#name.toString() ) + ":"
+ convertToString( o[ v.#name ] );
}
}
return "{" + s + "}";
}

Resources