Ihave an xml file sample.xml
<?xml version="1.0" standalone="yes"?>
<DataSchema xmlns="http://tempuri.org/DataSchema.xsd">
<ManagedObject>
<Label>sam</Label>
<Owner>00000000-0000-0000-0000-000000000000</Owner>
<ClassID>00000000-0000-0000-0000-000000000008</ClassID>
<DefaultApp>00000000-0000-0000-0000-000000000000</DefaultApp>
<Name>rvi</Name>
<version>9.6</version>
</ManagedObject>
</DataSchema>
i need to display 9.6 (9.6) from above xml file to the listview.I started a new windowform application. i added listview named "_listview" put its view as a "detail" mode.I added a column
there named _version
Can you give me the code to display version number in the listview column
if your XML file will have always this structre you can use simply:
string version = "";
int n = 0;
using (DataSet ds = new DataSet())
{
ds.ReadXml(#"sample.xml");
if(ds.Tables.Contains("ManagedObject")
&& ds.Tables["ManagedObject"].Rows.Count > n)
{
ver = ds.Tables["ManagedObject"].Rows[n]["version"].ToString();
}
}
to get the n-th ManagedObject version.
in your case you have only 1, so n = 0.
if you want to add "version" as an item that will appear in the first column of the listview:
listView1.Items.Add(version);
if "version" is to be added to an existing item in a secondary column use:
listview1.Items[n].SubItems.Add(version);
you can look here for further details.
this will also work fine
XmlDocument doc = new XmlDocument();
doc.Load(#"F:\xml\sample.xml");
XmlNamespaceManager nsmgr = new XmlNamespaceManager(doc.NameTable);
nsmgr.AddNamespace("sam", "http://tempuri.org/DataSchema.xsd");
XmlNode node = doc.SelectSingleNode(
"/sam:DataSchema/sam:ManagedObject/sam:version", nsmgr);
string version = node == null ? null : node.InnerText;
_listview.Items.Add(version);
Related
I have an XML file that contains multiple URLs for different image file sizes, and I'm trying to get a single url to load into a picture box. My issue is that the child nodes are named similarly, and the parent nodes are named similarly as well. For example, I want to pull the first medium image (ending in SL160_.jpg). See below for XML code
<Items>
<SmallImage>
<URL>http://ecx.images-amazon.com/images/I/51TAL%2Bn7AqL._SL75_.jpg</URL>
</SmallImage>
<MediumImage>
<URL>http://ecx.images-amazon.com/images/I/51TAL%2Bn7AqL._SL160_.jpg</URL>
</MediumImage>
<LargeImage>
<URL>http://ecx.images-amazon.com/images/I/51TAL%2Bn7AqL.jpg</URL>
</LargeImage>
<MediumImage>
<URL>http://ecx.images-amazon.com/images/I/51TAL%2Bn7AqL._SL162_.jpg</URL>
</MediumImage>
<LargeImage>
<URL>http://ecx.images-amazon.com/images/I/51TAL%2Bn7AqL.jpg</URL>
</LargeImage>
</Items>
I've tried using GetElementsByTag, as well as trying to call something like doc.SelectSingleNode("LargeImage").SelectSingleNode("URL").InnerText, and GetElementByID. All of these have given me an Object set to null reference exception.
What can I do to specify that I want the url from the first found MediumImage node?
Use LinqToXMLïĵIt is rather simple
string xml = #"<Items>
<SmallImage>
<URL>http://ecx.images-amazon.com/images/I/51TAL%2Bn7AqL._SL75_.jpg</URL>
</SmallImage>
<MediumImage>
<URL>http://ecx.images-amazon.com/images/I/51TAL%2Bn7AqL.01_SL160_.jpg</URL>
</MediumImage>
<LargeImage>
<URL>http://ecx.images-amazon.com/images/I/51TAL%2Bn7AqL.jpg</URL>
</LargeImage>
<MediumImage>
<URL>http://ecx.images-amazon.com/images/I/51TAL%2Bn7AqL.02_SL162_.jpg</URL>
</MediumImage>
<LargeImage>
<URL>http://ecx.images-amazon.com/images/I/51TAL%2Bn7AqL.jpg</URL>
</LargeImage>
</Items>";
XElement root = XElement.Parse(xml);
var ele = root.Elements("MediumImage").Where(e => e.Element("URL").Value.EndsWith("SL160_.jpg")).FirstOrDefault();
Console.WriteLine(ele);
In addition to Sky Fang's answer, I think the OP wants this:
var firstMedImg = root.Elements("MediumImage").First();
var imgUrl = firstMedImg.Element("URL").Value;
XmlDocument doc = new XmlDocument();
// PATH TO YOUR DOCUMENT
doc.Load("daco.xml");
// Select LIST ALL ELEMENTS SmallImage,MediumImage,LargeImage
XmlNodeList listOfAllImageElements = doc.SelectNodes("/Items/*");
foreach (XmlNode imageElement in listOfAllImageElements)
{
// Select URL ELEMENT
XmlNode urlElement= node.SelectSingleNode("URL");
System.Console.WriteLine(urlElement.InnerText);
}
Console.ReadLine();
If you want to select multiple url's
XmlDocument doc = new XmlDocument();
// PATH TO YOUR DOCUMENT
doc.Load("daco.xml");
// Select LIST ALL ELEMENTS SmallImage,MediumImage,LargeImage
XmlNodeList listOfAllImageElements = doc.SelectNodes("/Items/*");
foreach (XmlNode imageElement in listOfAllImageElements)
{
// Select URL's ELEMENTs
XmlNodeList listOfAllUrlElements = imageElement.SelectNodes("URL");
foreach (XmlNode urlElement in listOfAllUrlElements)
{
System.Console.WriteLine(urlElement.InnerText);
}
}
Console.ReadLine();
if you have specific namespace in your xml file
XmlDocument doc = new XmlDocument();
doc.Load("doc.xml");
XmlNamespaceManager man = new XmlNamespaceManager(doc.NameTable);
// reaplace http://schemas.microsoft.com/vs/2009/dgml with your namespace
man.AddNamespace("x", "http://schemas.microsoft.com/vs/2009/dgml");
// next you have to use x: in your path like this
XmlNodeList node = doc.SelectNodes("/x:Items/x:*, man);
I am trying to write a test function in C# that read data from an XML file and parse into Selenium testing methods , the XML code is like:
<home>
<ask_frame>
<button>
<id>Object ID<id>
<xpath>Object XPath<xpath>
<textbox>
<id>Object ID<id>
<xpath>Object XPath<xpath>
</ask_frame>
<search_frame>
<id>Object ID<id>
<xpath>Object XPath<xpath>
</search_frame>
<home>
I am trying to create a loop that read the id and xpath value from these nodes and parse them into an method for searching a webpage element by id and xpath. My initial attempt was:
Code updated
public void CheckIdTest()
{
driver.Navigate().GoToUrl(baseURL + "FlightSearch");
XmlDocument xd = new XmlDocument();
xd.Load(#"C:\XMLFile1.xml");
XmlNodeList mainlist = xd.SelectNodes("//home/*");
XmlNode mainroot = mainlist[0];
foreach (XmlNode xnode in mainroot)
{
string objID = xnode.SelectSingleNode("id").InnerText;
string objXPath = xnode.SelectSingleNode("XPath").InnerText;
objID = objID.Trim();
objXPath = objXPath.Trim();
String checkValue = "ObjID value is: " + objID + Environment.NewLine+ "ObjXPath value is: " + objXPath;
System.IO.File.WriteAllText(#"C:\checkvalue.txt", checkValue);
objectCheck(objXPath, objID);
}
}
I have put a String and checked that correct values for ObjID and ObjXPath have been achieved, but this loop also went only twice (checked 2 nodes in first branch). How could I make it runs through every node in my XML?
Any suggestions and explanations to the code will be highly appreciated.
Basically these two lines are using incorrect XPath :
XmlNodeList idlist = xd.SelectNodes("id");
XmlNodeList xpathlist = xd.SelectNodes("XPath");
<id> and <xpath> nodes aren't located directly at the root level, so you can't access it just like above. Besides, xpath is case-sensitive so you should've used "xpath" instead of "XPath". Try to fix it like this :
XmlNodeList idlist = xd.SelectNodes("//id");
XmlNodeList xpathlist = xd.SelectNodes("//xpath");
or more verbose :
XmlNodeList idlist = xd.SelectNodes("home/*/id");
XmlNodeList xpathlist = xd.SelectNodes("home/*/xpath");
UPDATE :
Responding to your comment about looping problem, I think you want to change it like this :
foreach (XmlNode xnode in mainroot.ChildNodes)
{
string objID = xnode.SelectSingleNode("id").InnerText;
string objXPath = pathroot.SelectSingleNode("xpath").InnerText;
objectCheck(objID, objXPath);
}
You are getting this error because you are trying to use an object that is null i.e not instantiated.
Put in a breakpoint at the line
XmlDocument xd = new XmlDocument();
and step through line by line till you find where the nothing.null reference is.
It should not take long to find out what the problem is.
I'm writing an application which will need to index and store information about files fast. I'm currently using XML to store the information using this code:
XmlTextWriter xtw;
xtw = new XmlTextWriter(FilePath, Encoding.UTF8);
xtw.WriteStartDocument();
xtw.WriteStartElement("ApplicationIndex");
xtw.WriteEndElement();
xtw.Close();
XmlDocument xd = new XmlDocument();
FileStream lfile = new FileStream(FilePath, FileMode.Open);
xd.Load(lfile);
XmlElement cl = xd.CreateElement("Application");
cl.SetAttribute("Name", ApplicationName);
XmlElement na = xd.CreateElement("Path");
XmlText natext = xd.CreateTextNode(ApplicationPath);
na.AppendChild(natext);
cl.AppendChild(na);
XmlElement na1 = xd.CreateElement("UseCount");
XmlText natext1 = xd.CreateTextNode("0");
na1.AppendChild(natext1);
cl.AppendChild(na1);
XmlElement na2 = xd.CreateElement("SearchTerm");
XmlText natext2 = xd.CreateTextNode(ApplicationName.ToLower());
na2.AppendChild(natext2);
cl.AppendChild(na2);
xd.DocumentElement.AppendChild(cl);
lfile.Close();
xd.Save(FilePath);
This works fine for creating the file and storing the data, however I'm having trouble searching through the data quickly as there are several hundred nodes in the document. I've tried using Linq to XML to achieve this using this code:
listBox1.Items.Clear();
var doc = XDocument.Load(filePath);
foreach (var child in doc.Descendants("SearchTerm"))
{
if (child.Value.Contains(textBox1.Text.ToLower()))
{
listBox1.Items.Add(child.Value);
}
}
This is very fast however I can't seem to get any information about the selected node. For example I would like to sort the returned results based upon the UseCount (The higher the count the higher up the list). Is there anyway to do this in XML or any other technique to achieve this?
This is what the XML file looks like:
<?xml version="1.0" encoding="utf-8"?>
<ApplicationIndex>
<Application Name="Google Chrome">
<Path>C:\Program Files\Google\Chrome\Chrome.exe</Path>
<UseCount>0</UseCount>
<SearchTerm>google chrome</SearchTerm>
</Application>
<Application Name="Mozilla Firefox">
<Path>C:\Program Files\Mozilla\Firefox\Firefox.exe</Path>
<UseCount>0</UseCount>
<SearchTerm>mozilla firefox</SearchTerm>
</Application>
</ApplicationIndex>
You can Sort your elements by UseCount in descending order like this:
var doc = XDocument.Load(filePath);
var elements = doc.Descendants("Application")
.OrderByDescending(x => (int)x.Element("UseCount"));
In order to search a record by given SearchTerm you can do the following:
var element = doc.Descendants("Application")
.FirstOrDefault(x => (string)x.Element("SearchTerm") == value);
if(element != null)
{
// record found
}
I am having a problem renaming child nodes in xml files using c#.
This is my xml file:
<?xml version="1.0" encoding="ISO-8859-1"?>
<ZACAC01>
<IDOC BEGIN="1">
<ZACGPIAD SEGMENT="1">
<IDENTIFIER>D000</IDENTIFIER>
<CUST_DEL_NO/>
<CUST_DEL_DATE/>
<TRUCKNO/>
<DRIVERNAME/>
<DRIVERID/>
<RESPONS_OFF/>
<CONFIRM_DATE>20/01/13</CONFIRM_DATE>
<SERIAL_NO>2</SERIAL_NO>
<SERIAL_CHAR/>
<DEL_INFO1/>
<QTY>0</QTY>
<DEL_INFO2/>
<QTY>0</QTY>
<DEL_INFO3/>
<QTY>0</QTY>
<TRANS_COMPANY>0</TRANS_COMPANY>
</ZACGPIAD>
</IDOC>
</ZACAC01>
And below is my requirement:
<?xml version="1.0" encoding="ISO-8859-1"?>
<ZACAC01>
<IDOC BEGIN="1">
<ZACGPIADD SEGMENT="1">
<IDENTIFIER>D000</IDENTIFIER>
<CUST_DEL_NO/>
<CUST_DEL_DATE/>
<TRUCKNO/>
<DRIVERNAME/>
<DRIVERID/>
<RESPONS_OFF/>
<CONFIRM_DATE>20/01/13</CONFIRM_DATE>
<SERIAL_NO>2</SERIAL_NO>
<SERIAL_CHAR/>
<DEL_INFO1/>
<QTY1>0</QTY1>
<DEL_INFO2/>
<QTY2>0</QTY2>
<DEL_INFO3/>
<QTY3>0</QTY3>
<TRANS_COMPANY>0</TRANS_COMPANY>
</ZACGPIADD>
</IDOC>
</ZACAC01>
I am able to change the segment tag <ZACGPIAD> to this <ZACGPIADD> using the following code:
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(srcfile);
var root = xmlDoc.GetElementsByTagName("IDOC")[0];
var oldElem = root.SelectSingleNode("ZACGPIAD");
var newElem = xmlDoc.CreateElement("ZACGPIADD");
root.ReplaceChild(newElem, oldElem);
while (oldElem.ChildNodes.Count != 0)
{
newElem.AppendChild(oldElem.ChildNodes[0]);
}
while (oldElem.Attributes.Count != 0)
{
newElem.Attributes.Append(oldElem.Attributes[0]);
}
xmlDoc.Save(desfile);
But I can't change the <QTY> tag to <QTY1>, <QTY2>, <QTY3>
How can I do this?
I think you have the answer right in your code. You can use SelectSingleNode to pull the first <QTY> element with this:
var qtyNode = root.SelectSingleNode("ZACAC01/IDOC/ZACGPIADD/QTY[1]")
then use ReplaceChild on it's parent node. Then do the same for the second and third <QTY> nodes, replacing the '1' with '2' and '3' respectively.
You can use XDocument and operate on XElements which expose setter for node name (so you can simply set new name instead of doing node replacements):
var doc = XDocument.Load(srcfile);
var zacgpidNode = doc.Descendants("ZACGPIAD").First();
zacgpidNode.Name = "ZACGPIADD";
// now rename all QTY nodes
var qtyNodes = zacgpidNode.Elements("QTY").ToArray();
for (int i = 0; i < qtyNodes.Length; i++)
{
qtyNodes[i].Name = string.Format("{0}{1}", qtyNodes[i].Name, i+1);
}
doc.Save(desfile);
Having Descendants("ZACGPIAD").First() might not be suitable if your document structure is different than what you've shown in example. You can use XPathSelectElement method to have more control over what you'll be extracting:
var node = doc.XPathSelectElement("//IDOC[#BEGIN='1']/ZACGPIAD[#SEGMENT='1']");
Having problems getting NodeList.SelectSingleNode() to work properly.
My XML looks like this:
<?xml version="1.0" encoding="ISO-8859-1" standalone="yes"?>
<inm:Results xmlns:inm="http://www.namespace.com/1.0">
<inm:Recordset setCount="18254">
<inm:Record setEntry="0">
<!-- snip -->
<inm:Image>fileName.jpg</inm:Image>
</inm:Record>
</inm:Recordset>
</inm:Results>
The data is a long series of <inm:Record> entries.
I open the doc and get create a NodeList object based on "inm:Record". This works great.
XmlDocument xdoc = new XmlDocument();
xdoc.Load(openFileDialog1.FileName);
XmlNodeList xRecord = xdoc.GetElementsByTagName("inm:Record");
I start looping through the NodeList using a for loop. Before I process a given entry, I want to check and see if the <inm:Image> is set. I thought it would be super easy just to do
string strImage = xRecord[i].SelectSingleNode("inm:Image").InnerText;
My thinking being, "For the XRecord that I'm on, go find the <inm:Image> value ...But this doesn't work as I get the exception saying that I need a XmlNameSpaceManager. So, I tried to set that up but could never get the syntax right.
Can someone show me how to use the correct XmlNameSpaceManager syntax in this case.
I've worked around the issue for now by looping through all of the childNodes for a given xRecord, and checking the tag once I loop around to it. I would like to check that value first to see if I need to loop over that <inm:Record> entry at all.
No need to loop through all the Record elements, just use XPath to specify the subset that you want:
XmlDocument xdoc = new XmlDocument();
xdoc.Load(openFileDialog1.FileName);
XmlNamespaceManager manager = new XmlNamespaceManager(xdoc.NameTable);
manager.AddNamespace("inm", "http://www.inmagic.com/webpublisher/query");
XmlNodeList nodes = xdoc.SelectNodes("/inm:Results/inm:Recordset/inm:Record[inm:Image != '']", manager);
Using the LINQ to XML libraries, here's an example for retrieving that said node's value:
XDocument doc = XDocument.Load(openFileDialog1.FileName);
List<XElement> docElements = doc.Elements().ToList();
XElement results = docElements.Elements().Where(
ele => ele.Name.LocalName == "Results").First();
XElement firstRecord = results.Elements().Where(
ele => ele.Name.LocalName == "Record").First();
XElement recordImage = firstRecord .Elements().Where(
ele => ele.Name.LocalName == "Image").First();
string imageName = recordImage.Value;
Also, by the way, using Hungarian notation for a type-checked language is overkill. You don't need to prepend string variables with str when it will always be a string.
XmlNamespaceManager nsMgr = new XmlNamespaceManager(xdoc.NameTable);
string strImage = xRecord[i].SelectSingleNode("inm:Image",nsMgr).InnerText;
Should do it.
Using this Xml library, you can get all the records that have an Image child element with this:
XElement root = XElement.Load(openFileDialog1.FileName);
XElement[] records = root.XPath("//Record[Image]").ToArray();
If you want to be sure that the Image child contains a value, it can be expressed like this:
XElement[] records = root.XPath("//Record[Image != '']").ToArray();