Hi I'm new to XML file. I have the following format XML file and I only need to read the value for data name = "A2" in VC++.
How to read the value using the XML DOM methods without looping all the nodes?
I would use the System:: Xml:: Linq namespace to read the document.
It is easier to use to reach the attributes and elements.
I took your XML data and modified it slightly and loaded it with this code:
#include "stdafx.h"
using namespace System;
using namespace System::Collections::Generic;
using namespace System::Linq;
using namespace System::Xml::Linq;
int main(array<System::String ^> ^args)
{
//c:\science\DaniWeb\DW_417210_CPP_CLR_CON\XmlFile.xml
XDocument^ xd = XDocument::Load("XmlFile.xml");
// Put the elements in a List of XElements (easier to navigate)
List<XElement^>^ lst_xeData = Enumerable::ToList(xd->Element("root")->Elements("data"));
// Write the individual attributes and elements
Console::WriteLine(lst_xeData[0]->Attribute("name")->Value + "=" + lst_xeData[0]->Value);
Console::WriteLine(lst_xeData[1]->Attribute("name")->Value + "=" + lst_xeData[1]->Value);
Console::WriteLine(lst_xeData[2]->Attribute("name")->Value + "=" + lst_xeData[2]->Value);
// Loop through each attribute and element
for each (XElement^ xe in lst_xeData)
{
Console::WriteLine(xe->Attribute("name")->Value + "=" + xe->Value);
}
return 0;
}
To get the target value on the first query, I would do something like this:
#include "stdafx.h"
using namespace System;
using namespace System::Collections::Generic;
using namespace System::Linq;
using namespace System::Xml::Linq;
bool AttrNameEqA2(XElement^ xe)
{
return xe->Attribute("name")->Value->Equals("A2");
}
int main(array<System::String ^> ^args)
{
//c:\science\DaniWeb\DW_417210_CPP_CLR_CON\XmlFile.xml
XDocument^ xd = XDocument::Load("XmlFile.xml");
// Put the elements in a List of XElements (easier to navigate)
List<XElement^>^ lst_xeData = Enumerable::ToList(xd->Element("root")->Elements("data"));
Func<XElement^, bool>^ attrNameEqA2 = gcnew Func<XElement^, bool>(AttrNameEqA2);
// uses a custom query to retrieve the specific record where the Value inside the attribute "name" is "A2".
Console::WriteLine(Enumerable::First(Enumerable::Where(lst_xeData, attrNameEqA2))->Value->ToString());
return 0;
}
AND
You may need to add in the references to System.Core and System.Xml.Linq at the project level.
...and for the last tehnique (if I were to make this a permanent part of my library), I would do something like this:
#include "stdafx.h"
using namespace System;
using namespace System::Collections::Generic;
using namespace System::Linq;
using namespace System::Xml::Linq;
public ref class CLinqHelper
{
private:
static property String^ strKey;
public:
static CLinqHelper()
{
strKey = "";
attrNameEqKey = gcnew Func<XElement^, bool>(AttrNameEqKey);
}
static bool AttrNameEqKey(XElement^ xe)
{
return xe->Attribute("name")->Value->Equals(strKey);
}
static Func<XElement^, bool>^ attrNameEqKey;
static String^ GetValueFromXml(List<XElement^>^ lst_xeData, String^ strKey)
{
CLinqHelper::strKey = strKey;
return Enumerable::First(Enumerable::Where(lst_xeData, CLinqHelper::attrNameEqKey))->Value->ToString();
}
};
int main(array<System::String ^> ^args)
{
//c:\science\DaniWeb\DW_417210_CPP_CLR_CON\XmlFile.xml
XDocument^ xd = XDocument::Load("XmlFile.xml");
// Put the elements in a List of XElements (easier to navigate)
List<XElement^>^ lst_xeData = Enumerable::ToList(xd->Element("root")->Elements("data"));
Console::WriteLine(CLinqHelper::GetValueFromXml(lst_xeData, "A2"));
return 0;
}
The last two examples are what could most closely be called "Linq to XML in C++".
At first, it looks complex, but after a while, it is easier to understand.
Most examples show the delegate being gcnew'ed on every loop. I make a separate method that holds the Func for that purpose. In most curcumstances, I will put that Func outside of the class to ensure it is only created once.