C# code for getting XML element by certain attribute value - c#

I am creating XML document by reading some objects and adding them to proper place (inside xml tree structure). To be able to add it to proper place I need parent XmlNode so I could call parentNode.AppendChild(node);
How can I get XmlNode object if I know value of one of its attributes?
XmlDocument dom = new XmlDocument();
XmlNode parentNode = null;
XmlNode node = dom.CreateElement(item.Title); //item is object that I am writing to xml
XmlAttribute nodeTcmUri = dom.CreateAttribute("tcmUri");
nodeTcmUri.Value = item.Id.ToString();
node.Attributes.Append(nodeTcmUri);
parentNode = ??? - how to get XML node if I know its "tcmUri" attribute value (it is unique value, no other node has same "tcmUri" attribute value)

You can do this using SelectSingleNode function and xpath query as below
XmlNode parentNode = dom.SelectSingleNode("descendant::yournodename[#tcmUri='" + item.Id.ToString() + "']");
Where yournodename has to be replaced with the node name of the parent elements

Try this
XmlDocument doc = new XmlDocument();
doc.LoadXml(content);
XmlNodeList list = doc.SelectNodes("mynode");
foreach (XmlNode item in list)
{
if (item.Attributes["tcmUri"].Value == some_value)
{
// do what you want, item is the element you are looking for
}
}

Use following code:
var nodeList = doc.SelectNodes("<Node Name>[#tcmUri = \"<Value>\"]");
if(list.Count>0)
parentNode = list[0];
Replace <Node Name> with the node name which you want to make the parent node.
Replace the <Value> with the value of tcmUri attribute of the Node which you want to make the parent node.

XPath is your friend :
string xpath = String.Format("//parentTag[#tcmUri='{0}']", "tcmUriValueHere");
//or in case parent node name (parentTag) may varies
//you can use XPath wildcard:
//string xpath = String.Format("//*[#tcmUri='{0}']", "tcmUriValueHere");
parentNode = dom.SelectSingleNode(xpath)

Related

Pasting xml to console

I need to get data SHILS_V from XML file. I read .xml
XML code for example:
<SVED_PR_GS>
<ZGLV>
<VERSION>99</VERSION>
<DATA>9999</DATA>
<FILENAME>1234</FILENAME>
<FIRSTNAME>1234</FIRSTNAME>
</ZGLV>
<SVD>
<CODE></CODE>
<YEAR></YEAR>
<MONTH></MONTH>
</SVD>
<SV_PR_GS>
<OBSV>
<N_ZAP>1</N_ZAP>
<MO_SV_V>12345</MO_SV_V>
<SNILS_V>123456789</SNILS_V>
</OBSV>
</SV_PR_GS>
</SVED_PR_GS>
My code to read xml:
XmlDocument xml = new XmlDocument();
xml.Load(filename);
Console.WriteLine("this");
XmlNodeList nodes = xml.GetElementsByTagName("SVED_PR_GS/SV_PR_GS");
foreach (XmlNode n in nodes)
{
Console.WriteLine("in loop");
XmlNode snils_v = n["OBSV/SNILS_V"];
Console.WriteLine("Snils V: " + snils_v);
}
Where is the problem?
How to get the information from SNILS_V?
GetElementsByTagName expects a tagname, not an XPath expression, "SV_PR_GS" will work there. And the same goes for the indexer of your XmlNode instance called n, this XPath will not work n["OBSV/SNILS_V"], use a tagname there as well but you have to handle the extra OBSV child there.
Here is your adapted code that produces output for me:
XmlNodeList nodes = xml.GetElementsByTagName("SV_PR_GS");
foreach (XmlNode n in nodes)
{
Console.WriteLine("in loop");
// first get the OBSV element
XmlNode obsv = n["OBSV"];
// now we can reach the other childs
XmlNode snils_v = obsv["SNILS_V"];
// Value will be null for XmlElement types, use InnerText instead
Console.WriteLine("Snils V: {0}" , snils_v.InnerText);
}
Notice that the Value property will return null for XmlNode that are of type XmlElement. In the XmlNode.Value documentation it is stated:
null. You can use the XmlElement.InnerText or XmlElement.InnerXml properties to access the value of the element node.
As your SNILS_V element seem to contain just a value InnerText is appropriate here.
To select a single node from XML. You need to access that object using SelectSingleNode method.
xml.SelectSingleNode("xpath for node")
To get collection of nodes you can write
xml.SelectNodes("xpath for node collection")
You should be able to get the value as follows:
XmlDocument xml = new XmlDocument();
xml.Load(filename);
Console.WriteLine("this");
XmlNodeList nodes = xml.GetElementsByTagName("OBSV");
foreach (XmlNode n in nodes)
{
Console.WriteLine("in loop");
XmlNode snils_v = n.SelectSingleNode("SNILS_V");
Console.WriteLine("Snils V: " + snils_v.InnerText);
}

Can't find a certain node in XML

My problem is that I can't seem to get a list of nodes I need. I have tried multiple solutions and it doesn't seem to work. This is a part of my xml file:
<findItemsByCategoryResponse xmlns="http://www.ebay.com/marketplace/search/v1/services">
<ack>Success</ack>
<version>1.13.0</version>
<timestamp>2016-08-23T07:33:22.497Z</timestamp>
<searchResult count="100">
<item>
<itemId>152210133431</itemId>
<title>...</title>
<globalId>EBAY-GB</globalId>
<primaryCategory>
<categoryId>218</categoryId>
<categoryName>Magic the Gathering</categoryName>
</primaryCategory>
<galleryURL>
http://thumbs4.ebaystatic.com/m/meIDrVqhmbpQMYCxzeUvR9Q/140.jpg
</galleryURL>
<viewItemURL>
http://www.ebay.co.uk/itm/MTG-See-Unwritten-Khans-Tarkir-MYTHIC-MINT-/152210133431
</viewItemURL>
<paymentMethod>PayPal</paymentMethod>
<autoPay>false</autoPay>
<location>London,United Kingdom</location>
<country>GB</country>
<shippingInfo>
<shippingServiceCost currencyId="GBP">1.1</shippingServiceCost>
<shippingType>Flat</shippingType>
<shipToLocations>GB</shipToLocations>
</shippingInfo>
<sellingStatus>
<currentPrice currencyId="GBP">0.5</currentPrice>
<convertedCurrentPrice currencyId="GBP">0.5</convertedCurrentPrice>
<bidCount>0</bidCount>
<sellingState>Active</sellingState>
<timeLeft>P0DT0H19M12S</timeLeft>
</sellingStatus>
<listingInfo>
<bestOfferEnabled>false</bestOfferEnabled>
<buyItNowAvailable>false</buyItNowAvailable>
<startTime>2016-08-18T07:52:34.000Z</startTime>
<endTime>2016-08-23T07:52:34.000Z</endTime>
<listingType>Auction</listingType>
<gift>false</gift>
</listingInfo>
<condition>
<conditionId>1000</conditionId>
<conditionDisplayName>New</conditionDisplayName>
</condition>
<isMultiVariationListing>false</isMultiVariationListing>
<topRatedListing>false</topRatedListing>
</item>
</searchResult>
<paginationOutput>...</paginationOutput>
<itemSearchURL>...</itemSearchURL>
</findItemsByCategoryResponse>
Normally there are 100 item nodes in this xml file, I just shorted the file. I tried to get the ''item'' nodes and everything inside in a XmlNodeList, but when I debug it says it contains 0 items. After this I want to retrieve some data, as you can see in the code. Note: I tried a lot of xpath values!
Here is the code I used:
XmlDocument xmlText = new XmlDocument();
xmlText.Load(basicUrl);
XmlElement root = xmlText.DocumentElement;
XmlNodeList xnList = root.SelectNodes("//item");
foreach(XmlNode item in xnList)
{
string title = item["title"].InnerText;
Console.WriteLine(title);
}
XPath Expressions are always namespace aware (if the Element has a Namespace then the XPath must reference it by namespace). Also, in XPath expressions, the 'default' namespace is always in the URI "". In your case you should do something like this :
XmlDocument xmlText = new XmlDocument();
xmlText.Load(yourXml);
XmlElement root = xmlText.DocumentElement;
XmlNamespaceManager nsmgr = new XmlNamespaceManager(xmlText.NameTable);
nsmgr.AddNamespace("t", "http://www.ebay.com/marketplace/search/v1/services");
XmlNodeList xnList = xmlText.SelectNodes("//t:item", nsmgr);
foreach (XmlNode item in xnList)
{
string title = item["title"].InnerText;
Console.WriteLine(title);
}
SelectNodes with namespace :
https://msdn.microsoft.com/en-US/library/4bektfx9(v=vs.110).aspx

Selecting value from first xml child node

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

How to get the value for multiple subnode in xml?

Xml code:
<Report>
<ChartData>
<ListName>area</ListName>
<ViewName>Selecte List</ViewName>
<YAxisFields>
<YAxisField>
<Name>Scheduled Start Date/Time</Name>
<DataType>DateTime</DataType>
<Category>Year</Category>
</YAxisField>
</YAxisFields>
<XAxisFields>
<XAxisField>
<Name>Release Type</Name>
<DataType>String</DataType>
<Category>
</Category>
</XAxisField>
</XAxisFields>
</ChartConfig>
</Report>
I got the value for the subnode listname and viewname by using the
below code,
XmlDocument doc = new XmlDocument();
doc.Load("XmlFileName");
XmlNodeList node = doc.SelectNodes("Report/ChartData");
foreach (XmlNode xn in node)
{ xn["ListName"].InnerXml = chartname;
xn["ViewName"].InnerXml = SelectedList;
**xn["YAxisFields/YAxisField"].InnerXml = yaxisfield; //not working, need to get the value for this xml node,need help in this line dono how to proceed**
doc.Save("XmlFilename");
}
First i have tried with code like this instead of above code,in this
i need to create number of objects in order get the value for each
node so i tried by creating object for xmlnodelist then i used
foreach loop to get the value for each node but in this couldnt get
the value for YAxisFields/YAxisField because it also has parent node
as YAxisFields and subnode as YAxisField so there is only way to
create number of objects for xmlnode or is there any other way to do
this?
XmlDocument doc = new XmlDocument();
doc.Load("XmlFileName");
XmlNode Listnode = doc.SelectSingleNode("Report/ChartData/ListName");
XmlNode Viewnode = doc.SelectSingleNode("Report/ChartData/ViewName");
if (Listnode != null)
{
Listnode.InnerXml = chartname;
Viewnode.InnerXml = SelectedList; ;
doc.Save("XmlFileName");
Use Linq to XML XDocument, like this:
doc.Root.Descendants("ChartData").ToList().ForEach(node =>
{
node.Element("ListName").Value = chartname;
node.Element("ViewName").Value = SelectedList;
});

Help with looping through an XML in C#

I have an xml that looks like this
<words>
<word>word1</word>
<word>word2</word>
<word>word3</word>
<word>word4</word>
</words>
I would like to loop through the "word" tags and just output the innertext for now.
how would I do this?
here is what i am doing now but is says the list of nodes count is 1
string _badWordFileDocPath = //my file path;
XmlDocument badWordDoc = new XmlDocument();
badWordDoc.Load(_badWordFileDocPath);
XmlElement root = badWordDoc.DocumentElement;
XmlNodeList nodes = root.SelectNodes("/words");
foreach(XmlNode node in nodes)
{
Console.WriteLine(node.InnerText);
}
Thanks!
You are selecting the root words node itself, rather than the child word nodes. Add /word to your XPath:
XmlNodeList nodes = root.SelectNodes("/words/word");
You need to move down the node tree one more layer:
foreach(XmlNode node in nodes)
{
XmlNodeList innerNodes = node.SelectNodes("/word");
foreach(Xmlnode innerNode in innerNodes )
{
Console.WriteLine(innerNode.InnerText);
}
}
I'd recommend using the classes in System.Xml.Linq for this task:
XElement wordsElement = XElement.Parse(yourXmlText);
var words = from w in wordsElement.Elements("word")
select w.Value;
You are missing /word in your XPath.
You can also use Linq (XDocument) to fetch the data.

Categories

Resources