Reading an XML document using pugiXml - c++

i have a problem with parsing an xml document using pugiXml, it seems to me that everything is correct but this code doesn't work :(
void MainWindow::open()
{
QString fileName = QFileDialog::getOpenFileName(this,"Open");
xml_document doc;
doc.load_file(fileName.toStdString().c_str());
for (pugi::xml_node node : doc.child("Person"))
{
qDebug(node.child_value("nom"));
qDebug(node.child_value("Age"));
}
}
Xml file format :
<?xml version="1.0"?>
<Persons>
<Person>
<nom>Med</nom>
<Age>12</Age>
</Person>
<Person>
<nom>Nasr</nom>
<Age>14</Age>
</Person>
<Person>
<nom>Souad</nom>
<Age>52</Age>
</Person>
</Persons>

The most probable cause is that you should use doc.child("Persons").
Document object in your case has one child Persons, that has several Person children. doc.child("Person") fails to find the node and returns a null handle.
Having said that, don't forget to check load_file return value as well.

Related

Add XML contained in string as XML nodes to existing pugixml tree

I have a configuration file saver/loader. In addition to the expected data, there is a <CustomData> node. When saving the node, we'd simply have a std::string _customData and add it to the node, like this:
pugi::xml_document doc;
pugi::xml_node config = doc.append_child("OurConfig");
// save custom data
pugi::xml_node customData = config.append_child("CustomData");
customData.append_child(pugi::node_pcdata).set_value(_customData);
Our _customData was base64 encoded XML. It is provided from another part of the application. It must be a string, since the other part of the application uses different programming language (C#). As you can imagine, that became annoying, because it wasn't human readable. First step to fix this was simply to get rid of base64 in the app that provides _customData. So now we have readable version, which looks like this:
<?xml version="1.0"?>
<OurConfig>
<CustomData><CfgRoot>
<SomeValue name="External setting for foo" value="Foo"/>
<SomeValue name="External setting for bar" value="Bar"/>
</CfgRoot></CustomData>
</OurConfig>
But it could probably improve if the custom data was directly appended to XML tree instead of as string value. How can I append XML string as XML and not as string to pugixml tree?
Ie. the output I'd like:
<?xml version="1.0"?>
<OurConfig>
<CustomData>
<CfgRoot>
<SomeValue name="External setting for foo" value="Foo"/>
<SomeValue name="External setting for bar" value="Bar"/>
</CfgRoot>
</CustomData>
</OurConfig>
In the docs, there are three methods listed. I used the first one, making a convenience function like this:
bool AppendXMLString(pugi::xml_node target, const std::string& srcString)
{
// parse XML string as document
pugi::xml_document doc;
if (!doc.load_buffer(srcString.c_str(), srcString.length()))
return false;
for (pugi::xml_node child = doc.first_child(); child; child = child.next_sibling())
target.append_copy(child);
return true;
}

Mapping unstructured schema elements into a structured

I just want to convert from this the hotel_info structure to the AvailableHotels structure: The hotel_info XML comes from a legacy SOAP web service and my goal is to the structure AvailableHotels ; The elements required from the hotel_info occur in various places
<hotel_info>
<AvailableHotels>
<hotel_1>
<hotelName_1>safd1</hotelName_1>
<booked_by>Taylor Volkes</booked_by>
<booking_id>sdf</booking_id>
</hotel_1>
<hotel_2>
<hotelName_1>safd2</hotelName_1>
<booked_by>Sam Volkes</booked_by>
<booking_id>sdf</booking_id>
</hotel_2>
</AvailableHotels>
<hotel_details>
<detail>
<hotelReference>hotel_1</hotelReference>
<reservation_complete>Yes</reservation_complete>
<hotelAddress1>sd</hotelAddress1>
<hotelAddress2>sd</hotelAddress2>
<hotelCity>sd</hotelCity>
<hotelState>sd</hotelCity>
<hotelState>AK</hotelState>
<suite_required>Yes</suite_required>
<email_provided>sdfeiwocmed</email_provided>
<hotelState__b_>HI</hotelState__b_>
</detail>
<detail>
<hotelReference>hotel_2</hotelReference>
<reservation_complete>Yes</reservation_complete>
<hotelAddress1>sd</hotelAddress1>
<hotelAddress2>sd</hotelAddress2>
<hotelCity>sd</hotelCity>
<hotelState>sd</hotelCity>
<hotelState>AK</hotelState>
<suite_required>Yes</suite_required>
<email_provided>sdfeiwocmed</email_provided>
<hotelState__b_>HI</hotelState__b_>
</detail>
</hotel_details>
<hotel_info>
To this:
<AvailableHotels>
<hotel>
<HotelName>hotel_1</HotelName>
<HotelAddressLine1Text></HotelAddressLine1Text>
<HotelAddressLine2Text></HotelAddressLine2Text>
<HotelCityName></HotelCityName>
<HotelStateCode></HotelStateCode>
<HotelZip5Code></HotelZip5Code>
<HotelZip4Code></HotelZip4Code>
<reservation_status>booked</reservation_status>
</hotel>
<hotel>
<HotelName>hotel_2</HotelName>
<HotelAddressLine1Text></HotelAddressLine1Text>
<HotelAddressLine2Text></HotelAddressLine2Text>
<HotelCityName></HotelCityName>
<HotelStateCode></HotelStateCode>
<HotelZip5Code></HotelZip5Code>
<reservation_status>booked</reservation_status>
<HotelZip4Code></HotelZip4Code>
</hotel>
</AvailableHotels>
How can I do this?
Step by step:
Create the output to render the AvailableHotels -hotel - HotelName part
create a variable curHotel with name() of the tags inside your AvailableHotels
use the parameter as selection criteria for apply-templates something along the lines of <xsl:apply-templates select="/hotel_info/hotel_details/detail[hotelReference=$curHotel]" />
(off my head, might contain typos)

Poco library for c++, declare namespace for custom element

I want to create an XML document by building a DOM document from scratch, with syntax like:
AutoPtr<Document> doc = new Document;
AutoPtr<Element> root = doc->createElement("root");
doc->appendChild(root);
AutoPtr<Element> element1 = doc->createElementNS("http://ns1", "ns1:element1");
root->appendChild(element1);
AutoPtr<Element> element2 = doc->createElementNS("http://ns1", "ns1:element2");
root->appendChild(element2);
DOMWriter writer;
writer.setNewLine("\n");
writer.setOptions(XMLWriter::PRETTY_PRINT);
writer.writeNode(std::cout, doc);
But, when I write it, I get next result:
<root>
<ns1:element1 xmlns:ns1="http://ns1"/>
<ns1:element2 xmlns:ns1="http://ns1"/>
</root>
So namespace ns1 declared two times, and I want to declare it inside "root" element.
Is there way to get next representation:
<root xmlns:ns1="http://ns1"/>
<ns1:element1/>
<ns1:element2/>
</root>

XML Getting attibute value of a Node

I am using XML DOM API in C++ to parse an XML file. I can't find any method to get the attribute value in a node element.
For example, in the following xml
<test>
<fruit count="10">
...
...
</fruit>
<test>
I need to get the count string("10") using XML APIs. Can anybody help me with some code snippets.
Use DOM Parser API to get attribute value count.
Refer below sample code:
//code to perform some process for parsing the input file and get rootElement
DOMNodeList* fruitNodes= rootElement->getElementsByTagName(XMLString::transcode("fruit"));
DOMNode* node = fruitNodes->item(0);
DOMElement* fruitElement = dynamic_cast <xercesc::DOMElement*>(node);
const XMLCh* attrValue = fruitElement->getAttribute(XMLString::transcode("count"));
you can get value 10 from attrValue using: string(XMLString::transcode(attrValue))
Based on http://msdn.microsoft.com/en-us/library/windows/desktop/ms754523(v=vs.85).aspx
Try something like:
pXMLDomNodeList = pXMLDocElement->selectNodes("/test/fruit/#count");

XML root element is null. Why?

I'm having a problem when I try to parse a XML, but I can not see why.
This is the XML:
<comments>
<comment>
<id>7</id>
<value>comment 1</value>
<document></document>
</comment>
</comments>
This is the my code:
DOMDocument* xmlDoc = request.parseXMLString(commentsXML);
DOMElement* rootEl = xmlDoc->getDocumentElement();
Debugging it, I got:
commentsXML = <comments><comment><id>7</id><value>comment 1</value><document></document></comment></comments>
rootEl = NULL (Why ?????)
Why my "rootEl" is null? Do you have a suggestion?
Thanks!
EDIT
I'm using Xerces (http://xerces.apache.org/xerces-c/)