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?

My xml file is as follows:

<?xml version="1.0" encoding="utf-8" ?>
<root>
<xsd:schema id= ......>
...
...
</xsd:schema>
...
...

<data name="A0">
<value>ja</value>
</data>
<data name="A1">
<value>display</value>
</data>
<data name="A2">
<value>Monitor</value>
</data>
...
...
</root>

Thank you

Recommended Answers

All 4 Replies

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;
}

...and here is the file I used:

<?xml version="1.0" encoding="utf-8" ?>
<root>
   <data name="A0">
      <value>ja</value>
   </data>
   <data name="A1">
      <value>display</value>
   </data>
   <data name="A2">
      <value>Monitor</value>
   </data>
</root>

Output attached:

I will have another (more to-the-point example shortly).

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.

Thank you very much

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.