Parsing XML and taking values from the file - regex

I need to get exact answer from my whole .xml file.
Let's say we have part of my .xml:
<trace>
<string key="concept:name" value="1"/>
<string key="description" value="Simulated process instance"/>
<event>
<string key="org:resource" value="System"/>
<date key="time:timestamp" value="1970-01-02T12:23:00.000+01:00"/>
<string key="concept:name" value="Register"/>
<string key="lifecycle:transition" value="complete"/>
</event>
<event>
<string key="org:resource" value="Tester3"/>
<date key="time:timestamp" value="1970-01-02T12:23:00.000+01:00"/>
<string key="concept:name" value="Analyze Defect"/>
<string key="lifecycle:transition" value="start"/>
</event>
<event>
<string key="defectType" value="6"/>
<string key="org:resource" value="Tester3"/>
<string key="lifecycle:transition" value="complete"/>
<string key="phoneType" value="T2"/>
<date key="time:timestamp" value="1970-01-02T12:30:00.000+01:00"/>
<string key="concept:name" value="Analyze Defect"/>
</event>
<event>
<string key="org:resource" value="SolverC1"/>
<date key="time:timestamp" value="1970-01-02T12:31:00.000+01:00"/>
<string key="concept:name" value="Repair (Complex)"/>
<string key="lifecycle:transition" value="start"/>
</event>
<event>
<string key="org:resource" value="SolverC1"/>
<date key="time:timestamp" value="1970-01-02T12:49:00.000+01:00"/>
<string key="concept:name" value="Repair (Complex)"/>
<string key="lifecycle:transition" value="complete"/>
</event>
<event>
<string key="org:resource" value="Tester3"/>
<date key="time:timestamp" value="1970-01-02T12:49:00.000+01:00"/>
<string key="concept:name" value="Test Repair"/>
<string key="lifecycle:transition" value="start"/>
</event>
<event>
<string key="numberRepairs" value="0"/>
<string key="org:resource" value="Tester3"/>
<string key="lifecycle:transition" value="complete"/>
<date key="time:timestamp" value="1970-01-02T12:55:00.000+01:00"/>
<string key="concept:name" value="Test Repair"/>
<string key="defectFixed" value="true"/>
</event>
<event>
<string key=" " value="System"/>
<date key="time:timestamp" value="1970-01-02T13:10:00.000+01:00"/>
<string key="concept:name" value="Inform User"/>
<string key="lifecycle:transition" value="complete"/>
</event>
<event>
<string key="numberRepairs" value="0"/>
<string key="org:resource" value="System"/>
<string key="lifecycle:transition" value="complete"/>
<date key="time:timestamp" value="1970-01-02T13:10:00.000+01:00"/>
<string key="concept:name" value="Archive Repair"/>
<string key="defectFixed" value="true"/>
</event>
</trace>
From here I need to find two exact "events". Event name is written in trace -> event -> string key="concept:name" value="EVENT NAME"
One of these events should have lifecycle:transition value="start", second one - "complete".
From "complete" event I need to take time:timestamp value="time" and subtract "start" event time:timestamp value="time".
So as you see the formula is time = time_complete - time_start
The problem is that time (time-date) format is not useful so from, e.g. 1970-01-02T12:30:00.000+01:00 I need to get only 12:30:00 and make it subtractable to find exact time how much the process took.
My idea it to get all event names in trace, all lifecycle transition values, and all "times" in this trace but I see that it's too difficult and I can find the proper way to do it. Here is some code from what I did:
NodeList nodeList = document.getElementsByTagName("trace");
Element element = (Element) nodeList.item(0);
NodeList stringList = element.getElementsByTagName("string");
NodeList dateList = element.getElementsByTagName("date");
//--- Get all events names ---//
for (int x = 1, size = stringList.getLength(); x < size; x++) {
if (stringList.item(x).getAttributes().getNamedItem("key").getNodeValue().contains("concept:name")) {
eventName.add(stringList.item(x).getAttributes().getNamedItem("value").getNodeValue());
}
}
//--- Get all times of every event in trace ---//
for (int y = 0, size = dateList.getLength(); y < size; y++) {
if (dateList.item(y).getAttributes().getNamedItem("key").getNodeValue().contains("time:timestamp")) {
time.add(dateList.item(y).getAttributes().getNamedItem("value").getNodeValue());
}
}
//--- Get all lifecycle transitions of events ---//
for (int x = 0, size = stringList.getLength(); x < size; x++) {
if (stringList.item(x).getAttributes().getNamedItem("key").getNodeValue().contains("lifecycle:transition")) {
status.add(stringList.item(x).getAttributes().getNamedItem("value").getNodeValue());
}
}

I think, that I solved my problem using the code:
SimpleDateFormat str = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'+'SS:SS");
Date data;
for (int i = 0; i < time.size(); i++) {
data = str.parse(time.get(i));
minutes.add(data.getHours() * 60 + data.getMinutes());
}
Anyway, thank you for your help :)

Related

How to set c++ boost graphml node and edge id?

I am using the Boost graph to store a set of nodes and edges and then write it to a graphml format. Whatever I do, I cannot find a way to access or set the node id (n0, n1) or edge id (e0) attributes.
It seems to be automatically set.
Is there a way to access and set it manually ?
<?xml version="1.0" encoding="UTF-8"?>
<graphml xmlns="http://graphml.graphdrawing.org/xmlns" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd">
<key id="key0" for="node" attr.name="id" attr.type="int" />
<key id="key1" for="edge" attr.name="length" attr.type="double" />
<key id="key2" for="edge" attr.name="max_speed" attr.type="double" />
<key id="key3" for="node" attr.name="name" attr.type="string" />
<key id="key4" for="edge" attr.name="name" attr.type="string" />
<key id="key5" for="edge" attr.name="source" attr.type="int" />
<key id="key6" for="node" attr.name="station" attr.type="boolean" />
<key id="key7" for="edge" attr.name="target" attr.type="int" />
<key id="key8" for="node" attr.name="theta" attr.type="double" />
<key id="key9" for="node" attr.name="x" attr.type="double" />
<key id="key10" for="node" attr.name="y" attr.type="double" />
<graph id="G" edgedefault="directed" parse.nodeids="canonical" parse.edgeids="canonical" parse.order="nodesfirst">
<node id="n0">
<data key="key0">10000</data>
<data key="key3">node1</data>
<data key="key6">0</data>
<data key="key8">0</data>
<data key="key9">6.95279e-310</data>
<data key="key10">0</data>
</node>
<node id="n1">
<data key="key0">10001</data>
<data key="key3">node1</data>
<data key="key6">0</data>
<data key="key8">0</data>
<data key="key9">6.95279e-310</data>
<data key="key10">0</data>
</node>
<edge id="e0" source="n0" target="n1">
<data key="key1">6.95279e-310</data>
<data key="key2">150</data>
<data key="key4"></data>
<data key="key5">-127787376</data>
<data key="key7">21994</data>
</edge>
</graph>
</graphml>
My graph
typedef typename boost::adjacency_list<boost::vecS, boost::vecS, boost::directedS,
GpNode, GpEdge>
DirectedGraph;
Where GpNode and GpEdge are custom class definitions.
Thanks in advance
write_graphml takes a dynamic_properties. Let's configure that:
Live On Coliru
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/graphml.hpp>
struct GpNode {
int id;
std::string name;
bool station;
double theta;
double x;
double y;
};
struct GpEdge {
double length;
double max_speed;
std::string name;
int source;
int target;
};
using DirectedGraph = boost::adjacency_list<boost::vecS, boost::vecS,
boost::directedS, GpNode, GpEdge>;
int main() {
std::ifstream ifs("input.xml");
DirectedGraph g;
auto n0 = add_vertex(
GpNode{
10000, // id
"node1", // name
0, // station
0, // theta
6.95279e-310, // x
0, // y
}, g);
auto n1 = add_vertex(
GpNode{
10001, // id
"node1", // name
0, // station
0, // theta
6.95279e-310, // x
0, // y
}, g);
/*auto e0 = */add_edge(n0, n1,
GpEdge{
6.95279e-310, // length
150, // max_speed
"", // name
-127787376, // source
21994, // target
}, g);
auto vindex = get(&GpNode::id, g);
boost::dynamic_properties dp;
//dp.property("node_id", vindex);
dp.property("id", vindex);
dp.property("name", get(&GpNode::name, g));
dp.property("station", get(&GpNode::station, g));
dp.property("theta", get(&GpNode::theta, g));
dp.property("x", get(&GpNode::x, g));
dp.property("y", get(&GpNode::y, g));
dp.property("length", get(&GpEdge::length, g));
dp.property("max_speed", get(&GpEdge::max_speed, g));
dp.property("name", get(&GpEdge::name, g));
dp.property("source", get(&GpEdge::source, g));
dp.property("target", get(&GpEdge::target, g));
boost::write_graphml(std::cout, g, dp);
}
Prints
<?xml version="1.0" encoding="UTF-8"?>
<graphml xmlns="http://graphml.graphdrawing.org/xmlns" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd">
<key id="key0" for="node" attr.name="id" attr.type="int" />
<key id="key1" for="edge" attr.name="length" attr.type="double" />
<key id="key2" for="edge" attr.name="max_speed" attr.type="double" />
<key id="key3" for="node" attr.name="name" attr.type="string" />
<key id="key4" for="edge" attr.name="name" attr.type="string" />
<key id="key5" for="edge" attr.name="source" attr.type="int" />
<key id="key6" for="node" attr.name="station" attr.type="boolean" />
<key id="key7" for="edge" attr.name="target" attr.type="int" />
<key id="key8" for="node" attr.name="theta" attr.type="double" />
<key id="key9" for="node" attr.name="x" attr.type="double" />
<key id="key10" for="node" attr.name="y" attr.type="double" />
<graph id="G" edgedefault="directed" parse.nodeids="free" parse.edgeids="canonical" parse.order="nodesfirst">
<node id="n0">
<data key="key0">10000</data>
<data key="key3">node1</data>
<data key="key6">0</data>
<data key="key8">0</data>
<data key="key9">6.95279e-310</data>
<data key="key10">0</data>
</node>
<node id="n1">
<data key="key0">10001</data>
<data key="key3">node1</data>
<data key="key6">0</data>
<data key="key8">0</data>
<data key="key9">6.95279e-310</data>
<data key="key10">0</data>
</node>
<edge id="e0" source="n0" target="n1">
<data key="key1">6.95279e-310</data>
<data key="key2">150</data>
<data key="key4"></data>
<data key="key5">-127787376</data>
<data key="key7">21994</data>
</edge>
</graph>
</graphml>
Mmm. That took a while. But now I see. I know that write_graphviz_dp assumes node_id is the node id property, but as you can see, I tried and it didn't help
Docs To The Rescue
But, wait, docs show a second overload that also takes VertexIndexMap. Let's.... try that?
boost::write_graphml(std::cout, g, vindex, dp);
Now it prints
Live On Coliru
<?xml version="1.0" encoding="UTF-8"?>
<graphml xmlns="http://graphml.graphdrawing.org/xmlns" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd">
<key id="key0" for="node" attr.name="id" attr.type="int" />
<key id="key1" for="edge" attr.name="length" attr.type="double" />
<key id="key2" for="edge" attr.name="max_speed" attr.type="double" />
<key id="key3" for="node" attr.name="name" attr.type="string" />
<key id="key4" for="edge" attr.name="name" attr.type="string" />
<key id="key5" for="edge" attr.name="source" attr.type="int" />
<key id="key6" for="node" attr.name="station" attr.type="boolean" />
<key id="key7" for="edge" attr.name="target" attr.type="int" />
<key id="key8" for="node" attr.name="theta" attr.type="double" />
<key id="key9" for="node" attr.name="x" attr.type="double" />
<key id="key10" for="node" attr.name="y" attr.type="double" />
<graph id="G" edgedefault="directed" parse.nodeids="free" parse.edgeids="canonical" parse.order="nodesfirst">
<node id="n10000">
<data key="key0">10000</data>
<data key="key3">node1</data>
<data key="key6">0</data>
<data key="key8">0</data>
<data key="key9">6.95279e-310</data>
<data key="key10">0</data>
</node>
<node id="n10001">
<data key="key0">10001</data>
<data key="key3">node1</data>
<data key="key6">0</data>
<data key="key8">0</data>
<data key="key9">6.95279e-310</data>
<data key="key10">0</data>
</node>
<edge id="e0" source="n10000" target="n10001">
<data key="key1">6.95279e-310</data>
<data key="key2">150</data>
<data key="key4"></data>
<data key="key5">-127787376</data>
<data key="key7">21994</data>
</edge>
</graph>
</graphml>
That's likely as close as you'll get with it. Changing the id type to std::string doesn't prevent the "n" prefix. (I suppose it's to allow edges to have id's colliding with nodes without problems?)

Boost Read_graphml doesn't read xml properly it gives all the vertices but they are empty

I have a adjacency list of type
boost::adjacency_list<boost::setS, boost::vecS, boost::directedS, GraphData>
Where GraphData is a structure contains name
struct GraphItem
{
std::string Name;
}
I am able to write graph to xml
void WriteGraph() {
boost::dynamic_properties dp;
dp.property("Name", make_transform_value_property_map(&Name,
boost::get(vertex_bundle, graph)));
boost::write_graphml(filename, graph, dp, true);
}
std::string Name(boost::vertex_bundle_type<Graph>::type v) {
std::ostringstream oss;
oss << v.Name;
return oss.str();
}
I get XML as
<graphml>
<key id="key0" for="node" attr.name="Name" attr.type="string" />
<graph id="G" edgedefault="directed" parse.nodeids="canonical"
parse.edgeids="canonical" parse.order="nodesfirst">
<node id="n0">
<data key="key0">A</data>
</node>
<node id="n1">
<data key="key0">D</data>
</node>
<node id="n2">
<data key="key0">B</data>
</node>
<node id="n3">
<data key="key0">C</data>
</node>
<edge id="e0" source="n0" target="n1">
</edge>
<edge id="e1" source="n2" target="n3">
</edge>
</graph>
</graphml>
When I read graph
void ReadGraph() {
boost::dynamic_properties dp;
std::ifstream file(fileName);
boost::read_graphml(file, graph, dp);
}
This is crashing says property Name not found.
If I use ignore_other_properties for property,
boost::dynamic_properties dp(ignore_other_properties);
It works but I am not getting any graph item in graph vertices.
The graph is not empty, you get:
0 --> 1
1 -->
2 --> 3
3 -->
Or in XML: https://paste.ubuntu.com/p/c4tGmxGssJ/
Of course, you wanted to read the name property. For that you obviously need to register the property with the dynamic-properties map.
Note You can access members of property bundles much simpler:
dp.property("Name", boost::get(&GraphData::Name, graph));
Full Demo
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/graphml.hpp>
struct GraphData {
std::string Name;
};
using Graph = boost::adjacency_list<boost::setS, boost::vecS, boost::directedS, GraphData>;
Graph ReadGraph(std::string const& fileName) {
Graph graph;
boost::dynamic_properties dp;
dp.property("Name", boost::get(&GraphData::Name, graph));
std::ifstream file(fileName);
boost::read_graphml(file, graph, dp);
return graph;
}
void WriteGraph(std::ostream& os, Graph& graph) {
boost::dynamic_properties dp;
dp.property("Name", get(&GraphData::Name, graph));
boost::write_graphml(os, graph, dp, true);
}
#include <boost/graph/graph_utility.hpp>
int main() {
Graph g = ReadGraph("input.txt");
print_graph(g, get(&GraphData::Name, g));
// or as XML
WriteGraph(std::cout << "==== XML version: ====\n\n", g);
}
Prints
A --> D
D -->
B --> C
C -->
==== XML version: ====
<?xml version="1.0" encoding="UTF-8"?>
<graphml xmlns="http://graphml.graphdrawing.org/xmlns" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd">
<key id="key0" for="node" attr.name="Name" attr.type="string" />
<graph id="G" edgedefault="directed" parse.nodeids="canonical" parse.edgeids="canonical" parse.order="nodesfirst">
<node id="n0">
<data key="key0">A</data>
</node>
<node id="n1">
<data key="key0">D</data>
</node>
<node id="n2">
<data key="key0">B</data>
</node>
<node id="n3">
<data key="key0">C</data>
</node>
<edge id="e0" source="n0" target="n1">
</edge>
<edge id="e1" source="n2" target="n3">
</edge>
</graph>
</graphml>

Copy operator not working in Quick Fast C++

Now currently I am working on copy operator. What I understand from all the document and other material available on net is that Quickfast maintains a dictionary which is used by multiples entries within a UDP message to check the previous value.
eg: Lets say in the below given template we can have multiple MDEntries depending upon NoMDEntries tag value. Lets say we have 2 as the value .
What I did was , I put the value of MDEntryType (with copy oprerator ) as 1 (some random value) in the first entry, but for the second entry I did not put any value.
After I decode the message the value of MDEntryType should be 1 for both the entries.
Is my understanding correct ?
<template dictionary="1" id="1" name="MDIncRefreshSample_1">
<string id="35" name="MessageType">
<constant value="X"></constant>
</string> <string id="49" name="SenderCompID">
<constant value="Client"></constant>
</string> <string id="56" name="TargetCompID">
<constant value="Server"></constant>
</string> <uint32 id="34" name="MsgSeqNum"></uint32>
<uint64 id="52" name="SendingTime"></uint64>
<sequence name="MDEntries">
<length id="268" name="NoMDEntries"></length>
<uint32 id="279" name="MDUpdateAction">
<copy value="1"></copy>
</uint32>
<string id="269" name="MDEntryType">
<copy value="0"></copy>
</string>
<uint32 id="278" name="MDEntryID"></uint32>
<uint32 id="48" name="SecurityID">
<delta></delta>
</uint32>
<decimal id="270" name="MDEntryPx">
<exponent>
<default value="-2"></default>
</exponent>
<mantissa>
<delta></delta>
</mantissa>
</decimal>
<int32 id="271" name="MDEntrySize">
<delta></delta>
</int32>
<string id="37" name="OrderID"></string>
<uint32 id="273" name="MDEntryTime">
<copy></copy>
</uint32>
</sequence>
</template>
Now when I try to implement the above in my code, I am not able to copy the value in the second entry.
Here is the snippet of the code I used (help taken from testRoundTrip.cpp)
Template Created :
<templates>
<template dictionary="InstrumentReferenceData"
name="InstrumentReferenceData" id="3">
<typeRef name="instrumentreferencedata"/>
<uInt32 name="timestamp" id="52"> <delta/> </uInt32>
<uInt32 name="srcId" id="50"> <copy/> </uInt32>
<uInt32 name="seqNum" id="34"> <increment value="1"/> </uInt32>
<uInt32 name="isix" id="48"> <delta/> </uInt32>
<string name="isin" id="455"> <delta/> </string>
<string name="exchId" id="207"> <copy/> </string>
<string name="instGrp" id="1151"> <copy/> </string>
<string name="instTypCod" id="461"> <copy/> </string>
<string name="currCode" id="15"> <copy/> </string>
<decimal name="ticSiz" id="969"> <delta/> </decimal>
<uInt32 name="setId" id="TBD"> <copy/> </uInt32>
<sequence name="MDFeedTypes">
<length name="noOfStreams" id="1141"/>
<string name="streamType" id="1022"> <copy dictionary="template" />
</string>
<string name="streamService"> <copy/> </string>
<string name="inetAddr"> <delta/> </string>
<uInt32 name="port" id="TBD"> <delta/> </uInt32>
<uInt32 name="mktDepth" id="264" presence="optional"/> </uInt32>
<uInt32 name="mdBookType" id="1021" presence="optional"/> </uInt32>
</sequence>
</template>
</templates>
Message creation plus encoding and decoding: (I have poulated the value in streamtype field only once)
Messages::MessagePtr msg(new Messages::Message(templateRegistry->maxFieldCount()));
msg->addField(identity_timestamp, Messages::FieldUInt32::create(1));
msg->addField(identity_srcId, Messages::FieldUInt32::create(2));
msg->addField(identity_seqNum, Messages::FieldUInt32::create(3));
msg->addField(identity_isix, Messages::FieldUInt32::create(4));
msg->addField(identity_isin, Messages::FieldAscii::create("isin"));
msg->addField(identity_exchId, Messages::FieldAscii::create("exchId"));
msg->addField(identity_instGrp, Messages::FieldAscii::create("instGrp"));
msg->addField(identity_instTypCod, Messages::FieldAscii::create("instTypCod"));
msg->addField(identity_currCode, Messages::FieldAscii::create("currCode"));
msg->addField(identity_ticSiz, Messages::FieldDecimal::create(Decimal(123, -1)));
msg->addField(identity_setId, Messages::FieldUInt32::create(5));
lengthIdentity.setId("1141");
Messages::SequencePtr sequence_MDFeedTypes(new Messages::Sequence(lengthIdentity, 2));
Messages::FieldSetPtr entry(new Messages::FieldSet(6)); // todo Hardcoded 6?
entry->addField(identity_streamType, Messages::FieldAscii::create("streamType")); // Populated the value 1st time
entry->addField(identity_streamService, Messages::FieldAscii::create("streamService"));
entry->addField(identity_inetAddr, Messages::FieldAscii::create("inetAddr.com"));
entry->addField(identity_port, Messages::FieldUInt32::create(2222));
entry->addField(identity_mktDepth, Messages::FieldUInt32::create(10));
sequence_MDFeedTypes->addEntry(Messages::FieldSetCPtr(entry));
entry.reset(new Messages::FieldSet(6));
entry->addField(identity_streamType, Messages::FieldAscii::create("")); // Did not Populate the value 2nd time
entry->addField(identity_streamService, Messages::FieldAscii::create(""));
entry->addField(identity_inetAddr, Messages::FieldAscii::create("inetAddr.org"));
entry->addField(identity_port, Messages::FieldUInt32::create(2224));
entry->addField(identity_mdBookType, Messages::FieldUInt32::create(3));
sequence_MDFeedTypes->addEntry(Messages::FieldSetCPtr(entry));
msg->addField(identity_MDFeedTypes, Messages::FieldSequence::create(sequence_MDFeedTypes));
Codecs::Encoder encoder(templateRegistry);
Codecs::DataDestination destination;
template_id_t templId = 3; // from the XML above
encoder.encodeMessage(destination, templId, *msg);
std::string fastString;
destination.toString(fastString);
std::cout<<"fastString is "<<fastString<<std::endl;
destination.clear();
Codecs::Decoder decoder(templateRegistry);
Codecs::DataSourceString source(fastString);
Codecs::SingleMessageConsumer consumer;
Codecs::GenericMessageBuilder builder(consumer);
decoder.decodeMessage(source, builder);
Messages::Message & msgOut(consumer.message());
Messages::MessageFormatter formatter(std::cout);
formatter.formatMessage(msgOut); // I have made some printing changes to print the ouptut per tag
validateMessage1(msgOut);
encoder.reset();
encoder.encodeMessage(destination, templId, msgOut);
std::string reencoded;
destination.toString(reencoded);
destination.clear();
I am able to encode and successfully decode the message, but the value is not getting copied in the second entry (streamType tag).
Here is my decoded ouput:
1st entry:
streamType[1022]=streamType
streamService[]=streamService
inetAddr[]=inetAddr.com
port[TBD]= 2045
2nd entry:
streamType[1022]= //value not copied
streamService[]=
inetAddr[]=inetAddr.org
port[TBD]= 2046
Could you please let us know, if we are making a mistake somewhere. I am very new to this :)
I have following queries too :
1/ Do we need to explicitly need to enable/disable dictionary in quickfast ? (In FIX we could do that with flag, DataDictionary = Y/N).
Also in the template created above , I found this line:
<string name="streamType" id="1022"> <copy dictionary="template" /> </string>
Is it neccesary to give dictionary name while using operators and how are they related?
2/ Do we also need to explicitly mention that PMAP bits are required?
Codecs::PresenceMap pmap(1); // I came across this function, so I got this doubt whether we need to explicitly mention about pmap.

Is it possible to generate non-blocking calls with dbusxx-xml2cpp?

I would like to generate C++ headers using dbusxx-xml2cpp where some methods are non-blocking, e.g. using invoke_method_noreply instead of invoke_method. Is this possible?
For example the following XML:
<?xml version="1.0" encoding="UTF-8" ?>
<node name="/me/MyService">
<interface name="me.MyService">
<method name="MyMethod">
<arg direction="in" type="s" name="argument"/>
</method>
</interface>
</node>
Would generate (partly):
void MyMethod(const std::string& argument)
{
::DBus::CallMessage call;
::DBus::MessageIter wi = call.writer();
wi << argument;
call.member("MyMethod");
::DBus::Message ret = invoke_method (call);
}
But I would like to have something like:
void MyMethod(const std::string& argument)
{
::DBus::CallMessage call;
::DBus::MessageIter wi = call.writer();
wi << argument;
call.member("MyMethod");
bool ret = invoke_method_noreply (call);
}
Use the annotation org.freedesktop.DBus.Method.NoReply"
Example XML:
<node>
<interface name="org.test.example">
<method name="NoReplyMethod">
<arg name="data" direction="in" type="i"/>
<annotation name="org.freedesktop.DBus.Method.NoReply" value="true"/>
</method>
</interface>
</node>
Generated Code:
void NoReplyMethod(const int32_t& data)
{
::DBus::CallMessage call;
::DBus::MessageIter wi = call.writer();
wi << data;
call.member("NoReplyMethod");
assert (invoke_method_noreply (call));
}

How to edit the end of the XML document end in Qt (writeEndDocument)?

I write a small program address book, contacts stored in the xml file. Here is the part off the code
void new_engine::main_window::write_to_db(const QString& n, const QString& s)
{
QFile m_db_file(m_db_path);
QString t("User");
m_db_file.open(QIODevice::Append);
QXmlStreamWriter wxml(&m_db_file);
wxml.setAutoFormatting(true);
if(m_size == 1)
{
wxml.writeStartDocument();
wxml.writeStartElement("Persons");
}
wxml.writeStartElement(t);
QString id = QString::number(m_size);
wxml.writeAttribute("id", id);
wxml.writeTextElement("Name", n);
wxml.writeTextElement("Surname", s);
wxml.writeEndElement();
wxml.writeEndDocument();
m_db_file.close();
}
but the problem is that after the first contact of the tag file is closed. here is the result
<?xml version="1.0" encoding="UTF-8"?>
<Persons>
<User id="1">
<Name>das</Name>
<Surname>vcvx</Surname>
</User>
</Persons>
<User id="2">
<Name>eqwevxcv</Name>
<Surname>xcvxcx</Surname>
</User>
<User id="3">
<Name>das</Name>
<Surname>dasdasd</Surname>
</User>
but it must be so
<Persons>
<User id="1">
<Name>das</Name>
<Surname>vcvx</Surname>
</User>
<User id="2">
<Name>eqwevxcv</Name>
<Surname>xcvxcx</Surname>
</User>
<User id="3">
<Name>das</Name>
<Surname>dasdasd</Surname>
</User>
</Persons>
How can we do this, after each new record will have to change document end ?
This is an example:
void write_to_db(QXmlStreamWriter& writer, QString id, QString name, QString surname)
{
writer.writeStartElement("User");
writer.writeAttribute(QXmlStreamAttribute("id", id));
writer.writeTextElement("Name", name);
writer.writeTextElement("Surname", surname);
writer.writeEndElement();
}
// This can be a file, or whatever iodevice your heart desires.
QString out;
QXmlStreamWriter writer(&out);
writer.writeStartDocument();
writer.writeStartElement("Persons");
write_to_db(writer, "1", "das", "vcvx");
write_to_db(writer, "2", "das", "vcvx");
write_to_db(writer, "3", "das", "vcvx");
writer.writeEndElement(); // Close <persons> tag
writer.writeEndDocument();
The output (using QXmlStreamWriter::setAutoFormatting/Indent):
<?xml version="1.0"?>
<Persons>
<User id="1">
<Name>das</Name>
<Surname>vcvx</Surname>
</User>
<User id="2">
<Name>das</Name>
<Surname>vcvx</Surname>
</User>
<User id="3">
<Name>das</Name>
<Surname>vcvx</Surname>
</User>
</Persons>