How to create a xml node using rapidxml - c++

Hi I want to create the following xml file in C++ using rapidxml on Linux.
How to add an element which is of type name.
<wrapit>
<mainNode>
<name>something1</name>
</mainNode>
</wrapit>
what my code generates looks like following which I don't want.
<wrapit>
<mainNode>
<name something1=""/>
</mainNode>
</wrapit>
I could not find much information for this. Few on wordpress but the xml formats are different.
Code snippet
xml_node<>* root = doc.allocate_node(node_element, "mainNode");
doc.append_node(root);
xml_node<>* child = doc.allocate_node(node_element,"name");
child->append_attribute(doc.allocate_attribute("something1"));
root->append_node(child);

ugg....
xml_node<>* child = doc.allocate_node(node_element,"name","something1");
does it.

Related

Tinyxml2 append function

I have been looking for a way to append my xml file using tinyxml2 but couldn't find anything. I would appreciate any help.
Here is my code:
function savedata() {
XMLNode * pRoot = xmlDoc.NewElement("Cars");
xmlDoc.InsertFirstChild(pRoot);
XMLElement * pElement = xmlDoc.NewElement("Brand");
pElement->SetText("Audi");
pRoot->InsertEndChild(pElement);
pElement = xmlDoc.NewElement("type");
pElement->SetText("4x4");
pRoot->InsertEndChild(pElement);
pElement = xmlDoc.NewElement("Date");
pElement->SetAttribute("day", 26);
pElement->SetAttribute("month", "April");
pElement->SetAttribute("Year", 2015);
pElement->SetAttribute("dateFormat", "26/04/2015");
pRoot->InsertEndChild(pElement);
XMLError eResult = xmlDoc.SaveFile("SavedData1.xml");
XMLCheckResult(eResult);
}
Everytime I run the function, the xml is overwritten and I want to append to the existing file.
My xml file:
<Cars>
<Brand>Audi</Brand>
<Whatever>anothercrap</Whatever>
<Date day="26" month="April" Year="2015" dateFormat="26/04/2015"/>
</Cars>
My root is and I want to append to the existing file. For example,
<Cars>
<Brand>Audi</Brand>
<type>4x4</type>
<Date day="26" month="April" Year="2015" dateFormat="26/04/2015"/>
<Brand>BMWM</Brand>
<type>truck</type>
<Date day="26" month="April" Year="2015" dateFormat="26/04/2015"/>
</Cars>
XML is structured data so a textual append would be tricky and possibly error-prone, as you would have to make sure you don't add the root node twice, and that you maintain indentation etc.
What might be easier is to load the XML, parse it with TinyXML, and write it back.
You can append if you use the FILE overload for xmldoc.Save.
FILE* file = fopen("myfile.xml","a");
xmlDoc.Save(file);
fclose(file);
You just have to be careful when doing this since it will mess up the doc if you're printing multiple root nodes. If you're doing this for logging purposes I would just leave out the root node entirely and just have whatever is reading the log back know to append them or just not even care about proper xml format.

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");

Why can't I use xpath to parse nodes in the default namespace?

I'm an XML newbie and I have an XML document (which I can't edit because it comes from somewhere else) but it has a root node like this:
<Configuration xmlns="http://schemas.mycomp.com/product/settings" version="2.0.0">
I'm trying to parse this document with msxml and xpath and I've done it successfully if I remove the xmlns attribute. For some reason, with this xmlns attribute in place, the document won't parse. I've attempted to set the msxml parse to recognise the document using:
m_pXMLDoc->setProperty( _bstr_t(L"AllowDocumentFunction"), _variant_t(true));
m_pXMLDoc->setProperty( _bstr_t(L"AllowXsltScript"), _variant_t(true));
m_pXMLDoc->setProperty( _bstr_t(L"SelectionLanguage"), _variant_t(L"XPath"));
m_pXMLDoc->setProperty( _bstr_t(L"SelectionNamespaces"), _variant_t(L"xmlns='http://schemas.mycomp.com/product/settings'"));
m_pXMLDoc->preserveWhiteSpace = VARIANT_FALSE;
m_pXMLDoc->resolveExternals = VARIANT_TRUE;
m_pXMLDoc->validateOnParse = VARIANT_FALSE;
From reading around it looks like xpath only works on the "no name" namespace and this document sets the default namespace so that it's no longer "no name". Can I set the namespace that xpath uses using MSXML?
From Microsoft : This behaviour is by design ...
See http://support.microsoft.com/kb/288147
Use prefixes with the namespaces when you specify the SelectionNamespaces property

Adding a stylesheet declaration in my xml using Xerces-C

I have an application in c++ using Xerces-C as main xml manipulation library.
I have my DOMDocument* and my parser and I want to set declarations.
I do the following:
parser->setValidationScheme(xercesc::XercesDOMParser::Val_Never);
parser->setDoSchema(false);
parser->setLoadExternalDTD(false);
I want to add:
<?xml-stylesheet type="text/xsl" href="my_xslt.xsl"?>
How can I do it?
You'll need to use the createProcessingInstruction on the DOMDocument
http://xerces.apache.org/xerces-c/apiDocs-3/classDOMDocument.html#ce898787ba20c00c85be63f28a358507
Once you've created it, append it to the DocumentElement.
Here is the code for doing this:
xercesc::DomDocument *doc;
// ... (initialize doc in some way)
auto root = doc->getDocumentElement();
auto stylesheet = doc->createProcessingInstruction
(X("xml-stylesheet"), X("type=\"text/xsl\" href=\"custom.xsl\""));
doc->insertBefore(stylesheet, root);
This way, the stylesheet information appears in the prolog of the document, which is the typical place for it. X() is some function that encodes a C-style string as a Xerces-compatible XMLCh-string.

bug of RapidXML when the value of a xml node is null

If the value of node in the xml is null, when we print the xml node, the node has no start tag, but only the end tag. For example:
xml_document<char> doc;
doc.append_node(doc.allocate_node(rapidxml::node_element, "mynode", ""));
ofstream ofs("test.xml");
ofs<<doc;
the content of test.xml is:
</mynode>
the expected content of test.xml is
<mynode></mynode>
Is this a bug of rapidxml
I do not know what version of RapidXml you're using. I've used few days ago the latest and works fine... this problem was fixed or it was a particular case of yours :)