Getting Specific Attribute of XML file - c++

I need to get a attribute of subchild, the tags of Subchild are all same, I need to Differentiate with the attribute's name .
XML:
<HEADER>
<TITLE>title</TITLE>
<AUTOR>DNL</AUTOR>
<PLATFORM>Windows</PLATFORM>
<TEST_ENV>HiL</TEST_ENV>
</Header>
<VARIABLES>
<VAR Name="ABC" Value="1hhh4"></VAR>
<VAR Name="EFG" Value="343hkn"></VAR>
<VAR Name="IHJ" Value="1asds12" ></VAR>
<VAR Name="LMO" Value="43hjjn"></VAR>
<VAR Name="PQR" Value="1sdf43"></VAR>
<VARIABLES>
Code until now:
void MainWindow::StartUpScriptSetter(QString xmlpath)
{
QString Title;
QString Platform;
QString Author;
QString TEST;
xmlget.load(xmlpath);
xmlget.findAndDescend("HEADER");
if(xmlget.find("TITLE"))
{
startup = xmlget.getString();
}
if(xmlget.find("PLATFORM"))
{
ini = xmlget.getString();
}
if(xmlget.find("AUTHOR"))
{
zbf_file = xmlget.getString();
}
if(xmlget.find("TEST_ENV"))
{
zbf_root = xmlget.getString();
}
xmlget.save(xmlpath)
}
until now I have successfully fetched all Attributes of HEADER, i want only specific attributes of VARIABLES
I need the value attribute of Name = LMO. How do I do it?

if(xmlget.findAndDescend("VARIABLES")) {
if(xmlget.find("VAR")) {
QString name = xmlget.getAttributeString("Name", "");
if(!name.isEmpty() && name.compare("What you are looking for") == 0)
QString value = xmlget.getAttributeString("Value");
}
}

Related

Reading child node of a child node

Below i have show a normal XML file:
<Header>
<Sub Name="" Value="" /Sub>
<Sub Name="" value="" /Sub>
.
.
.
.
</Header>
I read the above mentioned XML like this:
QStringList Name;
QStringList value;
QXmlGet xmlget;
xmlget.load(Sample.xml);
xmlget.findAndDescend("Header");
while(xmlget.findNext("Sub")
{
Name.append(xmlget.getAttributeString("Name". "Unknown"));
value.append(xmlget.getAttributeString("value". "Unknown"));
}
xmlget.save(Sample.xml);
But the xml i have right now is bit complicated.
XML:
<Header>
<Sub Name= "" Value = ""><Sub1 Name = ""></Sub1></Sub>
<Sub Name= "" value = "" /Sub>
<Sub Name= "" Value = ""><Sub1 Name = ""></Sub1></Sub>
.
.
.
</Header>
Any suggestions how do I read the <Sub1>
Something like this one (Tested! It works!)
QStringList Name;
QStringList value;
QXmlGet xmlget;
xmlget.load("Sample.xml");
xmlget.findAndDescend("Header");
QXmlPut xmlPut(xmlget); // init reference from the variable - xmlget
while(xmlget.findNext("Sub")) {
Name.append(xmlget.getAttributeString("Name", "Unknown"));
value.append(xmlget.getAttributeString("Value", "Unknown"));
xmlget.descend(); // now Sub is the parent element
if( xmlPut.hasChildren() ) {
while(xmlget.findNext("Sub1") { // finding relatively the parent - Sub
xmlPut.goTo(xmlget.element());
xmlPut.setAttributeString("Name", "NAME1");
xmlPut.setAttributeString("Value", "VALUE1");
}
} else {
xmlPut.putInt("IntTag", "IntValue"); // We create the child node (IntTag) of the parent (Sub)
xmlPut.setAttributeString("AttrName", "AttrValue"); // and add some attributes to it
}
xmlget.rise();
}
xmlPut.save("Sample.xml"); // Any file name to save the xml data
docs

C++ Pugixml get children of parent by attribute id

For example:
<levels>
<level id="1">
<somestuff></somestuff>
</level>
<level id="2">
<somestuff></somestuff>
</level>
</levels>
How do you get the data of level with id 1?
Now i am using pugi::xml_node level = levels.child("level") But that return all levels..
Regards,
GJJ
levels.find_child_by_attribute("level", "id", "1")
Try it:
for (pugi::xml_node ambil = doc.child("levels").child("level"); ambil; ambil = ambil.next_sibling("level"))
{
int id = ambil.attribute("id").as_int();
CCLog("%d",id);
}
foreach children & compare attribute value.
e.g.
for (const auto& node : levels.children("level"))
{
if (node.attribute("id").as_int() == 1)
{
// TODO: add ur code here
}
}

QT5 C++ QByteArray XML Parser

I get the following xml
<Tra Type="SomeText">
<tr>Abcdefghij qwertzu</tr>
<Rr X="0.0000" Y="0.0000" Z="0.0000" A="0.0000" B="0.0000" C="0.0000" />
<Ar A1="0.0000" A2="0.0000" A3="0.0000" A4="0.0000" A5="0.0000" A6="0.0000" />
<Er E1="0.0000" E2="0.0000" E3="0.0000" E4="0.0000" E5="0.0000" E6="0.0000" />
<Te T21="1.09" T22="2.08" T23="3.07" T24="4.06" T25="5.05" T26="6.04" T27="7.03" T28="8.02" T29="9.01" T210="10.00" />
<D>125</D>
<IP></IP>
</Tra>
through a socket that saves it in a QByteArray called Data.
I want to extract and save every value from the xml to different variables (some as Integers some as QString's).
My main problem is that I dont know how to distinguish xml strings like <D>125</D> with a value in between the Tags and xml strings like <Te T210="10.00" T29="9... /> that got the value in the Tag-String itself.
My code looks like this so far:
QByteArray Data = socket->readAll();
QXmlStreamReader xml(Data);
while(!xml.atEnd() && !xml.hasError())
{
.....
}
There's just so many examples already, aren't there? =(
Anyway, like Frank said, if you want to read data (characters) from within tags - use QXmlStreamReader::readElementText.
Alternatively, you can do this:
QXmlStreamReader reader(xml);
while(!reader.atEnd())
{
if(reader.isStartElement())
{
if(reader.name() == "tr")
{
reader.readNext();
if(reader.atEnd())
break;
if(reader.isCharacters())
{
// Here is the text that is contained within <tr>
QString text = reader.text().toString();
}
}
}
reader.readNext();
}
For attributes, you should use QXmlStreamReader::attributes which will give you a container-type class of attributes.
QXmlStreamReader reader(xml);
while(!reader.atEnd())
{
if(reader.isStartElement())
{
if(reader.name() == "Rr")
{
QXmlStreamAttributes attributes = reader.attributes();
// This doesn't check if the attribute exists... just a warning.
QString x = attributes.value("X").toString();
QString y = attributes.value("Y").toString();
QString a = attributes.value("A").toString();
// etc...
}
}
reader.readNext();
}

Get content between tags using TinyXML

How can I get content between tags
<name> </name> and <mode> </mode>
<news>
<name>Enter</name>
<actions>
<mode>me</mode>
</actions>
</news>
You should really have a look at the excellent documentation of TinyXML as well as the tutorial. However, what you are looking for is the GetText() method of TiXmlElement.
Once you've arrived at your "name" or "mode" elements, you can get the string between these tags with GetText().
\ this
TiXmlDocument doc("tes.xml");
if (doc.LoadFile())
{
TiXmlHandle hDoc(&doc);
TiXmlText* text = hDoc.ChildElement("news", 0).ChildElement("act-news", 0).ChildElement("name", 0).FirstChild().Text();
if(text)
{
const char* message = text->Value();
cout<<(message)<<endl;
}
TiXmlText* stext = hDoc.ChildElement("news", 0).ChildElement("act-news", 1).ChildElement("name", 0).FirstChild().Text();
if(text)
{
const char* message = stext->Value();
cout<<(message)<<endl;

Runtime error with tinyXML element access

yester day was my first attempt. I am trying to catch the variable "time" in the following "new.xml" file
<?xml version="1.0" standalone=no>
<main>
<ToDo time="1">
<Item priority="1"> Go to the <bold>Toy store!</bold></Item>
<Item priority="2"> Do bills</Item>
</ToDo>
<ToDo time="2">
<Item priority="1"> Go to the Second<bold>Toy store!</bold></Item>
</ToDo>
</main>
Here is my code
TiXmlDocument doc("new.xml");
TiXmlNode * element=doc.FirstChild("main");
element=element->FirstChild("ToDo");
string temp=static_cast<TiXmlElement *>(element)->Attribute("time");
But I am getting run time errors from the third and fourth lines. Can anybody shed a light on this isssue?
It seems to me that you forgot to load the file. Normally I do something along these lines:
TiXmlDocument doc("document.xml");
bool loadOkay = doc.LoadFile(); // Error checking in case file is missing
if(loadOkay)
{
TiXmlElement *pRoot = doc.RootElement();
TiXmlElement *element = pRoot->FirstChildElement();
while(element)
{
string value = firstChild->Value(); // In your example xml file this gives you ToDo
string attribute = firstChild->Attribute("time"); //Gets you the time variable
element = element->NextSiblingElement();
}
}
else
{
//Error conditions
}
Hope this helps
#include "tinyXml/tinyxml.h"
const char MY_XML[] = "<?xml version='1.0' standalone=no><main> <ToDo time='1'> <Item priority='1'> Go to the <bold>Toy store!</bold></Item> <Item priority='2'> Do bills</Item> </ToDo> <ToDo time='2'> <Item priority='1'> Go to the Second<bold>Toy store!</bold></Item> </ToDo></main>";
void main()
{
TiXmlDocument doc;
TiXmlHandle docHandle(&doc);
const char * const the_xml = MY_XML;
doc.Parse(MY_XML);
TiXmlElement* xElement = NULL;
xElement = docHandle.FirstChild("main").FirstChild("ToDo").ToElement();
int element_time = -1;
while(xElement)
{
if(xElement->QueryIntAttribute("time", (int*)&element_time) != TIXML_SUCCESS)
throw;
xElement = xElement->NextSiblingElement();
}
}
That's how it works. Compiled & tested.
As you can see your tries to make it extra-safe code cost you with an exceotion at your third line (of the question), and without testing I can bet it's a "pointing-to-null" exception.
Just load it my style, as TinyXml's docs say as well: "docHandle.FirstChild("main").FirstChild("ToDo").ToElement();".
Hope it helps you understand, let me know if it's not clear. I accept visa (:
Is it just me or the the pugixml version looks much better?
#include <iostream>
#include "pugixml.hpp"
using namespace std;
using namespace pugi;
int main()
{
xml_document doc;
if (!doc.load_file("new.xml"))
{
cerr << "Could not load xml";
return 1;
}
xml_node element = doc.child("main");
element = element.child("ToDo");
cout << "Time: " << element.attribute("time") << endl;
}
Also new.xml had an error, instead of:
<?xml version="1.0" standalone=no>
should be
<?xml version="1.0" standalone="no"?>
Compilation was just a matter of cl test.cpp pugixml.cpp