I`m try to realize how to use TinyXML library.
I have to parse this conf file:
<?xml version="1.0" encoding="UTF-8"?>
<Client>
<port num = "20035">
<server_addr ip="127.0.0.1">
<AV_list>
<AV>
<AVNAME>BitDefender</AVNAME>>
<AVPATH> C:\Program Files\Common Files\BitDefender\BitDefender Threat Scanner\av64bit_26308\bdc.exe </AVPATH>
<AVMASK>0x80000000</AVMASK>
<AVCOMMANDLINE> %avpath% \log=%avlog% %scanpath% </AVCOMMANDLINE>
<AVREGEX>(%scanpath%.*?)+(([a-zA-Z0-9]+\\.)+[a-zA-Z]{2,4})+(.+[a-zA-Z_])</AVREGEX>
<AVLOG>C:\log\bd_log.txt</AVLOG>
</AV>
</AV_list>
</Client>
And c++ code
#include "stdafx.h"
#include "iostream"
#include "tinyxml.h"
int main(int argc, char* argv[])
{
TiXmlDocument doc( "D:\\client_conf.xml" );
bool loadOkay = doc.LoadFile();
if ( loadOkay )
printf("Yes \n");
else
printf("No \n");
TiXmlHandle hDoc(&doc);
TiXmlElement* pElem;
TiXmlText* pText;
TiXmlHandle hRoot(0);
pElem = hDoc.FirstChildElement().Element();
if (!pElem)
printf("error element");
hRoot = TiXmlHandle(pElem);
pElem = hRoot.FirstChild("server_addr").Element();
const char* info = pElem->Attribute("ip");
printf( "%s \n", info);
pElem = hRoot.FirstChild("port").Element();
info = pElem->Attribute("num");
printf( "%s \n", info);
system("pause");
return 0;
}
Now I can get first two param, but dont figure out how to reach "AV_list" block. Any help will be appreciated. (:
Have a look at the TinyXml Documentation. Your friend is the TiXmlNode Class Reference. You may use most of the Node functions also on TiXmlElements.
You already use the FirstChild() function to get the first child of an element; use the NextSibling() function to iterate over all elements. You can also use the NextSiblingElement() function to get the element directly.
Antother more sophisticated solution would be to use XPath to retrieve elements from the xml file. There is TinyXPath that builds on top of TinyXML. It needs some knowledge of XPath but it might be worth it. (XPath standard)
Related
I am using TinyXML2 and I got some strange problem. So It seems it work because I dont have any crashes but when I want to output one of the value I got I have nothing , if someone know why ?
I already used tinyxml2 and it was working but here maybe the XML is strange?
#include <iostream>
#include "tinyxml2/tinyxml2.cpp"
#include "../Inc/classConfigCtx.h"
#include "../Inc/globalDefine.h"
using namespace tinyxml2;
int main() {
std::cout << "Hello World!";
XMLDocument doc;
doc.LoadFile( "NetworkConfig.xml" );
int AppliMsgPort_;
const char * portAppli;
const char * IPtemp;
XMLElement * pRootElement =doc.RootElement()->FirstChildElement();
portAppli=pRootElement->FirstChildElement()->GetText();
std::cout<<portAppli;
return 0;
}
and my XML
<configuration>
<operational_00001000><name value="100.CBD" /><radio_1><type value="Net" /><ip value="10.36.1.1" /><port_s value="50010" /><port_r value="50100" /><radioID value="10040" /></radio_1></operational_00001000>
<operational_00001005><name value="100.LOG" /><radio_1><type value="Net" /><ip value="10.26.2.1" /><port_s value="50000" /><port_r value="50000" /><radioID value="1000005" /></radio_1></operational_00001005>
</configuration>
I'm trying to search all files that follow this pattern "console-*" and move them to another path on my machine if they exist. (For example from: /documents/fs/pstore to /sdk/sys/kernel_dump/).
#include <iostream>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
int dirExists(const char *pathname)
{
struct stat info;
if( stat( pathname, &info ) != 0 )
return 0; // printf( "cannot access %s\n", pathname );
else if( info.st_mode & S_IFDIR ) // S_ISDIR() doesn't exist on my windows
return 1; // printf( "%s is a directory\n", pathname );
else
return 0; // printf( "%s is no directory\n", pathname );
}
int main()
{
const char *path = "/documents/fs/pstore";
if(dirExists(path))
system("mv /documents/fs/pstore/console-* /sdk/sys/kernel_dump/ ");
else
printf( "error" );
return 0;
}
I've experienced with the code above, but it does not seem to work properly, should I try another approach, maybe with the rename() function? (I'm working on Linux)
Any advice would be greatly appreciated, thank you in advance.
You can call glob() and rename() C functions in Linux if C++17's std::filesystem is not an option for you. glob() gives you the list of files that matches globbing pattern like *, ? and []. However, rename() may fail if the mount position of from and to path are not identical. In this case, you should create your own copy and remove file function.
Hi i use rapidxml to load map in my game this is how my class for loading looks like
it's normally compiling but when loading file sometimes it crashing so i wanted to debug it but debugger dont like my function which is setting pointers to data in xml file.
#0 0042D5A6 rapidxml::xml_node<char>::first_node(this=0x0, name=0x484175 <_ZSt16__convert_from_vRKPiPciPKcz+4735349> "MapInfo", name_size=7, case_sensitive=true) (C:/.../rapidxml.hpp:942)
#1 00404E31 MapLoader::SetNodes(this=0x27fc1c) (C:\...\main.cpp:651)
#2 004032F6 main() (C:\...\main.cpp:267)
class MapLoader
{
public:
xml_document<> doc;
file<>xmlFile(char);
string ca,cb,cc,cd;
xml_node<> *test;
xml_node<> *root;
xml_node<> *mapinfo;
xml_node<> *name;
xml_node<> *date;
xml_node<> *msize;
xml_attribute<> *sizex;
xml_attribute<> *sizey;
xml_node<> *mapdata;
xml_node<> *layer;
xml_attribute<> *nr;
xml_node<> *tile;
xml_attribute<> *id;
xml_attribute<> *x;
xml_attribute<> *y;
void LoadFile(const char *filename);
void SetNodes();
void FillVector();
void SaveVector();
};
void MapLoader::SetNodes()
{
root=doc.first_node("root");
mapinfo=root->first_node("MapInfo"); //////debugger is pointing on this line
name=mapinfo->first_node("Name");
date=mapinfo->first_node("Date");
msize=mapinfo->first_node("Size");
sizex=msize->first_attribute("x");
sizey=msize->first_attribute("y");
mapdata=root->first_node("MapData");
layer=mapdata->first_node("Layer");
nr=layer->first_attribute("id");
tile=layer->first_node("Tile");
id=tile->first_attribute("id");
x=tile->first_attribute("x");
y=tile->first_attribute("y");
}
what i can do to repair it or something like that?
Edit:
here is my xml file:
<?xml version="1.0" encoding="utf-8"?>
<root>
<MapInfo>
<Name>Test</Name>
<Date>17.08.2014</Date>
<Size x="64" y="64"/>
</MapInfo>
<MapData>
<Layer nr="1">
<Tile id="1" x="32" y="32"/>
<Tile id="1" x="32" y="64"/>
<Tile id="1" x="512" y="64"/>
</Layer>
<Layer nr="2"/>
<Layer nr="3"/>
</MapData>
</root>
First of all its good practice to check for NULL as returned pointer. My guess would be, that "root" is missing in the xml file.
Take a look at the Manual of rapidxml because case sensitivity can also be an issue.
Edit:
I wrote a small program and checked at least Name and Date. Works for me.
// Trying out rapid xml.
//
#include "rapidxml/rapidxml.hpp"
#include <cstdio>
#include <string>
#include <vector>
int main(int argc, char** argv) {
rapidxml::xml_document<> doc; // character type defaults to char
FILE* file = fopen("Test.xml", "r");
if (!file)
return 1;
// file exists.
// get the number of bytes.
fseek(file, 0, SEEK_END);
size_t sizeInBytes = ftell(file);
fseek(file, 0, SEEK_SET);
char* buffer = static_cast<char*>(malloc(sizeInBytes + 1)); // + 1 needed?
if (fread(buffer, 1LU, sizeInBytes, file) != sizeInBytes) {
perror("unexpected file length\n");
fclose(file);
free(buffer);
return 1;
}
buffer[sizeInBytes] = 0;
// close the file.
fclose(file);
doc.parse<0>(buffer); // 0 means default parse flags
std::vector<std::string> nodeNames;
nodeNames.push_back("Name");
nodeNames.push_back("Date");
rapidxml::xml_node<>* node = doc.first_node("root");
for (size_t i = 0; i < nodeNames.size() && node; ++i) {
if (node->first_node(nodeNames[i].c_str()))
fprintf(stderr, "CantFindNode with name %s.\n", nodeNames[i].c_str());
printf("Node %s found!\n", nodeNames[i].c_str());
}
free(buffer);
return 0;
}
i am writing a c++ function that will parse .xml file.
i Used system("grep"); type system call to use linux command. now my problem is that i want to select more than one line in given tag. ex.
content of .xml file
====================
<state>
<text> hi this is first li </text>
<sec> dsfn sdlkf sfd </sec>
</state>
===================
i want to print all content between and tag. which and how i can use linux commands.
plz help me....thanks i advance.
Parsing XML using grep is really not a good idea, you should use some c++ xml parsing library like this one:
http://xerces.apache.org/xerces-c/index.html
exec, execve or system calls: demo
#include <stdlib.h>
#include <unistd.h>
int main(int argc, const char* args[])
{
exitcode = system("xsltprox textonly.xslt input.xml > output");
// exitcode = exec("xsltproc", "textonly.xslt", "input.xml");
int exitcode;
}
Proceed to fopen output (or std::fstream reader("output") if you fancy). Note that system is quickly a security hole, so you shouldn't use it in critical apps (like daemons).
Using exec you could redirect. So you could perhaps open a pipe() from your program, fork(), in the child assign the stdout filedescriptor to the pipe() (see dup2 call) and exec in the child.
The parent process can then read the output from the pipe without need for a temp file.
All of this should be on a zillion tutorials, which I don't have to the time to google for you right now.
May I suggest using perl or shell script. If you post an actual example I could show you the code in both shell and c/c++
Update here is how to do it with XSLT
textonly.xslt:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" indent="yes"/>
<xsl:template match="/">
<xsl:for-each select="//*[text()]">
<xsl:if test="text()">
<xsl:value-of select="text()"/>:
</xsl:if>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
output demo:
o399hee#OWW00837 ~/stacko
$ xsltproc.exe textonly.xslt input.xml
:
hi this is first li :
dsfn sdlkf sfd :
Use the C functions popen() and pclose()
Here's an example of how to use them:
#include <string>
#include <cstdio>
#include <errno.h>
#include <fstream>
int execShellCommand( const std::string command,
std::string& commandOutput )
{
FILE *fp;
char charBuf;
std::ostringstream stdoutBuffer;
int status;
std::ostringstream errmsg;
// Execute command and save its output to stdout
fp = popen( command.c_str( ), "r" );
if ( fp == NULL ) {
// error handling
} else {
while ( ( charBuf = fgetc( fp ) ) != EOF ) {
stdoutBuffer << charBuf;
}
}
// Wait for completion of command and return its exit status
status = pclose( fp );
if ( status == -1 ) {
// error handling
} else {
commandOutput = stdoutBuffer.str( );
return WEXITSTATUS( status ); // convert exit status
}
}
int main(){
std::string command = "l | grep lib";
std::string commandOutput;
int exitCode = execShellCommand( command, commandOutput);
}
I'm having a heck of a time figuring out how to use the sax parser for libxml2. Can someone post an example that parses this XML ( yes, without the <xml...> header and footer tags, if that can be parsed by the libxml2 sax parser):
<hello foo="bar">world</hello>
The parser should print out the data enclosed in element hello and also grab the value of attribute foo.
I'm working on this example, but hoping that someone else beats me to the punch since I'm not making much progress. The Google hasn't yielded any complete, working examples for libxml2 sax parser.
Adapted from http://julp.developpez.com/c/libxml2/?page=sax
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <libxml/tree.h>
#include <libxml/parser.h>
#include <libxml/parserInternals.h>
void start_element_callback(void *user_data, const xmlChar *name, const xmlChar **attrs) {
printf("Beginning of element : %s \n", name);
while (NULL != attrs && NULL != attrs[0]) {
printf("attribute: %s=%s\n",attrs[0],attrs[1]);
attrs = &attrs[2];
}
}
int main() {
const char* xml_path = "hello_world.xml";
FILE *xml_fh = fopen(xml_path,"w+");
fputs("<hello foo=\"bar\" baz=\"baa\">world</hello>",xml_fh);
fclose(xml_fh);
// Initialize all fields to zero
xmlSAXHandler sh = { 0 };
// register callback
sh.startElement = start_element_callback;
xmlParserCtxtPtr ctxt;
// create the context
if ((ctxt = xmlCreateFileParserCtxt(xml_path)) == NULL) {
fprintf(stderr, "Erreur lors de la création du contexte\n");
return EXIT_FAILURE;
}
// register sax handler with the context
ctxt->sax = &sh;
// parse the doc
xmlParseDocument(ctxt);
// well-formed document?
if (ctxt->wellFormed) {
printf("XML Document is well formed\n");
} else {
fprintf(stderr, "XML Document isn't well formed\n");
//xmlFreeParserCtxt(ctxt);
return EXIT_FAILURE;
}
// free the memory
// xmlFreeParserCtxt(ctxt);
return EXIT_SUCCESS;
}
This produces output:
Beginning of element : hello
attribute: foo=bar
attribute: baz=baa
XML Document is well formed
Compiled with the following command on Ubuntu 10.04.1:
g++ -I/usr/include/libxml2 libxml2_hello_world.cpp /usr/lib/libxml2.a -lz\
-o libxml2_hello_world
Can I suggest rapidxml?