tinyxml and c++ to save data - c++

I am using tinyxml to save data input by the user in a c++ console program. I pass a save function an array of structs that look like the following
struct day
{
string name;
string note;
};
I have seven of these, and pass all seven to the save function that looks like the following
void saveData(day dayArr[])
{
TiXmlDeclaration* declaration = new TiXmlDeclaration("1.0", "UTF-8", "no");//Create DTD
TiXmlDocument* doc = new TiXmlDocument;
doc->LinkEndChild(declaration);
TiXmlElement* week = new TiXmlElement("week");
TiXmlElement* day = new TiXmlElement("day");
TiXmlElement* name = new TiXmlElement("name");
TiXmlElement* note = new TiXmlElement("note");
TiXmlElement* tl = new TiXmlElement("tl");
TiXmlElement* ti = new TiXmlElement("ti");
TiXmlText* dayName = new TiXmlText("");
TiXmlText* dayNote = new TiXmlText("");
for(int i=0; i<7; i++)
{
dayName = new TiXmlText(dayArr[i].name.c_str());
dayNote = new TiXmlText(dayArr[i].note.c_str());
name->LinkEndChild(dayName);
note->LinkEndChild(dayNote);
day->LinkEndChild(name);
day->LinkEndChild(note);
}
week->LinkEndChild(day);
doc->LinkEndChild(week);
doc->SaveFile("test.xml");
cout << "SAVED";
}
It writes this to the file
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<week>
<day>
<name>SundayMondayTuesdayWednesdayThursdayFridaySaturday
</name>
<note>
</note>
</day>
</week>
What i need is this
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<week>
<day>
<name>Sunday</name>
<note> </note>
</day>
<day>
<name>Monday</name>
<note>
</note>
</day>
<day>
<name>Tuesday</name>
<note> </note>
</day>
<day>
<name>Wednesday</name>
<note> </note>
</day>
<day>
<name>Thursday</name>
<note> </note>
</day>
<day>
<name>Friday</name>
<note> </note>
</day>
<day>
<name>Saturday</name>
<note> </note>
</day>
</week>
I can't figure out how to create new elements of the day tag. Thanks in advance for any help.

I haven't used TinyXml before but looking at the structure of the code, you need to create the day element inside your for loop and add it to the week element 7 times - once for each day.
Your current code only adds the day element to the week element once at the end - this is reflected in your xml output.
Taking part of your code - maybe something similar to this below. (This may not compile or be exactly correct but should provide the right idea).
TiXmlElement* week = new TiXmlElement("week");
TiXmlElement* name = new TiXmlElement("name");
TiXmlElement* note = new TiXmlElement("note");
TiXmlElement* tl = new TiXmlElement("tl");
TiXmlElement* ti = new TiXmlElement("ti");
TiXmlText* dayName = new TiXmlText("");
TiXmlText* dayNote = new TiXmlText("");
for(int i=0; i<7; i++)
{
TiXmlElement* day = new TiXmlElement("day");
dayName = new TiXmlText(dayArr[i].name.c_str());
dayNote = new TiXmlText(dayArr[i].note.c_str());
name->LinkEndChild(dayName);
note->LinkEndChild(dayNote);
day->LinkEndChild(name);
day->LinkEndChild(note);
week->LinkEndChild(day);
}
doc->LinkEndChild(week);

void saveData(std::vector<day*> vecDay)
{
TiXmlDeclaration* declaration = new TiXmlDeclaration("1.0", "UTF-8", "no");//Create DTD
TiXmlDocument* doc = new TiXmlDocument;
doc->LinkEndChild(declaration);
TiXmlElement* week = new TiXmlElement("week");
for(std::vector<day*>::iterator it = vecDay.begin(); it != vecDay.end(); it++)
{
TiXmlElement* day_ = new TiXmlElement("day");
TiXmlElement* name = new TiXmlElement("name");
TiXmlElement* note = new TiXmlElement("note");
TiXmlElement* tl = new TiXmlElement("tl");
TiXmlElement* ti = new TiXmlElement("ti");
TiXmlText* dayName = new TiXmlText("");
TiXmlText* dayNote = new TiXmlText("");
dayName = new TiXmlText((*it)->name.c_str());
dayNote = new TiXmlText((*it)->note.c_str());
name->LinkEndChild(dayName);
note->LinkEndChild(dayNote);
day_->LinkEndChild(name);
day_->LinkEndChild(note);
week->LinkEndChild(day_);
}
doc->LinkEndChild(week);
doc->SaveFile("test2.xml");
cout << "SAVED" << endl;
}

Related

Deleting specific node of XML file

Below I have a sample of my XML file, I want to delete a specific node in each header. How do i do it. for example in header<HEADER> i want to delete the node <ADDRESS>, not just its attribute but the whole node. in <HEADER1> I need to delete the attribute <UMG_VAR Name="ABC" Value=1></UMG_var>, here Name attribute is unique.
<MAIN>
<HEADER>
<TITLE>ppc_ph_pios</TITLE>
<AUTOR>DNL</AUTOR>
<AGE>age</AGE>
<SEX>Male</SEX>
<PLACE>Earth</PLACE>
<ADDRESS>abc</ADDRESS>
</HEADER>
<HEADER1>
<UMG_VAR Name="RED" Value="3"></UMG_VAR>
<UMG_VAR Name="ABC2" Value="2"></UMG_VAR>
<UMG_VAR Name="ABC" Value="1"></UMG_VAR>
</HEADER2>
</MAIN>
QDomDocument doc;
doc.setContent(oldXml);
QDomNodeList nodes = doc.elementsByTagName("element");
for (int i = 0; i < nodes.count(); ++i)
{
QDomNode node = nodes.at(i);
QDomElement child = node.firstChildElement("child");
if (!child.isNull() && child.attribute("id") == "0")
{
node.removeChild(child);
}
}
QString newXml = doc.toString();

pass xml variable into c# method in xslt

i have xslt transform where im using c# code to save input and output xml to database.
but it saves only the values of all tags.
but i want to save vhole xml.
<msxsl:script language="CSharp" implements-prefix="ConnectDatabase">
<msxsl:assembly name = "System.Data"/>
<msxsl:using namespace = "System.Data"/>
<msxsl:using namespace = "System.Data.SqlClient"/>
<msxsl:using namespace = "System.Collections.Generic"/>
<![CDATA[
public void LogINOUT(string inputxml, string outputxml)
{
SqlCommand cmd = null;
string command = "INSERT INTO dbo.XsltLog (InputXml,OutputXml) VALUES (#inputxmlpar,#outputxmlpar)";
string connectionString ="Data Source=MyConneCtionStiring;
SqlParameter inputxmlpar = new SqlParameter("#inputxmlpar", SqlDbType.NVarChar);
inputxmlpar.Value=inputxml;
SqlParameter outputxmlpar = new SqlParameter("#outputxmlpar", SqlDbType.NVarChar);
outputxmlpar.Value =outputxml;
using (SqlConnection connection = new SqlConnection(connectionString))
{
cmd = new SqlCommand(String.Format(command), connection);
cmd.Parameters.Add(inputxmlpar);
cmd.Parameters.Add(outputxmlpar);
connection.Open();
cmd.ExecuteScalar();
}
}
]]></msxsl:script>
then a call it <xsl:copy-of select ="ConnectDatabase:LogINOUT( $inputxml,$outputxml)" />
and outputxml in database is something like this:
TO_TESTY45000.0000000020
from this string i know nothing
i wont its
<Data>
<Result>TO_TEST</Result>
<IncludeInVolume>Y</IncludeInVolume>
<FinancedAmont>
<xsl:value-of select="/Contract/ContractCalculations/Calculation/CalculationStep[#Code='FinancedAmount']"/>
</FinancedAmont>
<NumberOfInstalments>
<xsl:value-of select="format-number(/Contract/ContractCalculations/Calculation/CalculationStep[#Code='InstalmentNumber'],'#')"/>
</NumberOfInstalments>
</Data>
the same problem its with inputxml
thanks for Help Dana

How to delete nested xml element using qt

i have xml file like this
<root>
<element>
<child id = "0"> Some Text </child> <-- Target To Delete
</element>
<element>
<child id = "1"> Some Text </child>
</element>
</root>
how can i delete child element of id "0" ? using Qt library.
QDomDocument doc;
doc.setContent(oldXml);
QDomNodeList nodes = doc.elementsByTagName("element");
for (int i = 0; i < nodes.count(); ++i)
{
QDomNode node = nodes.at(i);
QDomElement child = node.firstChildElement("child");
if (!child.isNull() && child.attribute("id") == "0")
{
node.removeChild(child);
}
}
QString newXml = doc.toString();

Program crashes when trying to Add Element to Existing Node

I'm trying to add an Element into an already existing Node/Parent like so:
<?xml version="1.0" encoding="UTF-8" standalone="true"?>
<BitComet Version="1.0">
<MyShares>
<bt title="Sound of Music" save_path="C:\Downloads|Sound of Music" task_finished="true" category="software" size="7126369" hash="31e0ded5b561ed698c151e72d5f20d9b75f03b12"/>
</MyShares>
</BitComet>
--
TiXmlDocument xml(pf);
if(!xml.LoadFile()) return;
TiXmlElement* root = xml.FirstChildElement("BitComet");
TiXmlElement* parent = xml.FirstChildElement("MyShares")
TiXmlElement* elem = new TiXmlElement( "bt" );
elem->SetAttribute("title", "TiTlE");
elem->SetAttribute("save_path", "C:\\Downloads|Test");
elem->SetAttribute("task_finished", "true");
elem->SetAttribute("category", "software");
elem->SetAttribute("size", 7126369);
elem->SetAttribute("hash", "hash_here");
xml.LinkEndChild( elem );
xml.LinkEndChild( parent );
xml.LinkEndChild( root );
xml.SaveFile(pf);
I'm not sure what is happening, but it crashes when it executes that section of code.
I think that your call to access the <MyShares> tag should be
TiXmlElement* parent = root -> FirstChildElement("MyShares");
Also, the only LinkEndChild call you want is the following:
parent->LinkEndChild( elem );

How do I create child elements using msxml parser?

I have a users.xml
<?xml version="1.0"?>
<Data>
<Users>
<User name="xyz" email="xyz#xyz.com">
<Tasks/>
</User>
</Users>
</Data>
I have got a reference to Users element using the following code
IXMLDOMDocumentPtr pXMLDom;
// code to load the xml dox
IXMLDOMElementPtr pXMLDocElement = NULL;
IXMLDOMNodeListPtr pXMLUsers = NULL;
//gets <Data>
pXMLDocElement = pXMLDom->GetdocumentElement();
//gets <Users>
pXMLUsers = pXMLDocElement->childNodes;
Now how do I create a child element User in Users element.
I have tried using createElement() on pXMLUsers, but it says IXMLDOMNodeListPtr has no member appendChild.
I don't know how to create a new element.
Thanks.
You cannot use the IXMLDOMNodeListPtr to append a child - it's just for iterating existing children.
You can use the IXMLDOMElementPtr directly to call pXMLDocElement->appendChild() to add a child element in your Document.
Ok, I've found a solution, thanks to TERACytE
IXMLDOMDocumentPtr pXMLDom;
// code to load the xml dox
//Creating <User>
MSXML2::IXMLDOMElementPtr pUser = pXMLDom->createNode(NODE_ELEMENT, "User", "");
//Creating <User name="">
MSXML2::IXMLDOMAttributePtr pName = pXMLDom->createAttribute("name");
pName->value = name;
//Creating <User email="">
MSXML2::IXMLDOMAttributePtr pEmail = pXMLDom->createAttribute("email");
pEmail->value = email;
//Adding name attrib to <User>
pUser->setAttributeNode(pName);
//Adding email attrib to <User>
pUser->setAttributeNode(pEmail);
//Creating <Tasks>
MSXML2::IXMLDOMElementPtr pTasks = pXMLDom->createNode(NODE_ELEMENT, "Tasks", "");
//Creating <Task>
MSXML2::IXMLDOMElementPtr pTask = pXMLDom->createNode(NODE_ELEMENT, "Task", "");
//Creating <Task name="">
MSXML2::IXMLDOMAttributePtr pTName = pXMLDom->createAttribute("name");
pTName->value = task;
//Creating <User status="">
MSXML2::IXMLDOMAttributePtr pStatus = pXMLDom->createAttribute("status");
pStatus->value = status;
//Adding name attrib to <User>
pTask->setAttributeNode(pTName);
//Adding status attrib to <User>
pTask->setAttributeNode(pStatus);
//Adding <Task> to <Tasks>
pTasks->appendChild(pTask);
//Adding <Tasks> to <User>
pUser->appendChild(pTasks);
//Selecting <Users>
MSXML2::IXMLDOMNodePtr pUsers = pXMLDom->selectSingleNode("/Data/Users");
//Adding <User> to <Users>
pUsers->appendChild(pUser);