Check if an element exists when parsing XML
[Edit]Jon Skeet's answer should be the accepted answer. It is far more readable and easier to apply.[/edit]
Create an extension method like this :
public static string TryGetElementValue(this XElement parentEl, string elementName, string defaultValue = null)
{
var foundEl = parentEl.Element(elementName);
if (foundEl != null)
{
return foundEl.Value;
}
return defaultValue;
}
then, change your code like this :
select new News()
{
id = noticia.TryGetElementValue("IdNoticia"),
published = noticia.TryGetElementValue("Data"),
title = noticia.TryGetElementValue("Titol"),
subtitle = noticia.TryGetElementValue("Subtitol"),
thumbnail = noticia.TryGetElementValue("Thumbnail", "http://server/images/empty.png")
};
This approach allows you to keep a clean code with isolating the check of element presence. It also allow you to define a default value, which can be helpful
how to check if XML element exists or not?
- First of all, the path is incorrect.
/
is the path separator for xml path, not\\
. - You should not specify the
rootName
in the xml path since you already calling theSelectSingleNode
function for the root node (xmlDoc.DocumentElement
) - The way you identify non-existence node incorrect.
SelectSingleNode
does not throw an exception if the path does not exist. Instead, it simply returnsNothing
.
Based on the above, here are the modified code :
Dim xmlDoc As New XmlDocument()
xmlDoc.Load("C:\Users\Desktop\XMLFILE.xml")
Dim nodes As XmlNode
Try
nodes = xmlDoc.DocumentElement.SelectSingleNode("PRODUCT/NAME")
If nodes Is Nothing Then
MessageBox.Show("Not exists")
Else
MessageBox.Show("Exists")
End If
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
To use the SelectSingleNode
from the root, use the following path :
xmlDoc.SelectSingleNode("descendant::PRODUCT/NAME")
Check if specific xml node exists
Use linq to xml with Descendants
:
Returns a filtered collection of the descendant elements for this document or element, in document order. Only elements that have a matching XName are included in the collection.(Inherited from XContainer.)
var abcs = XDocument.Load("data.xml").Descendants("ABC");
if(abcs.Any())
{
// There is at least one element of "ABC"
}
PHP check if element exists in XML
SimpleXML implements different interfaces for the properties. If you use it like a string it will return the content of the first matching element. If you use it like a list, you can iterate all matching elements.
$products = new SimpleXmlElement($xml);
foreach ($products->product as $product) {
foreach ($product->properties->prop as $property) {
var_dump((string)$property->property);
}
}
Output:
string(5) "Farbe"
string(13) "Geeignet für"
string(10) "Verpackung"
string(12) "Gesamturteil"
string(8) "Garantie"
string(16) "Art der Garantie"
I would suggest defining an array of default values for each propid
that you like to read. The propid
should be more stable then the title and is not language specific. In the inner loop you validate that the id of the current exists in that array and assign the value
or valueid
.
foreach ($products->product as $product) {
// default values for each product property by `prodid`
$row = [
'25' => '',
'41' => ''
];
foreach ($product->properties->prop as $property) {
$id = (string)$property->propid;
if (array_key_exists($id, $row)) {
$row[$id] = (string)$property->value;
}
}
var_dump($row);
}
Output:
array(2) {
[25]=>
string(5) "Weiß"
[41]=>
string(6) "Unisex"
}
This way the result will always have the same count and order of elements.
Fetching specific elements if they existsTo fetch a specific property use Xpath. For example to fetch the property with the propid
25:
foreach ($products->product as $product) {
$colors = $product->xpath('properties/prop[propid = 25]');
if (count($colors) > 0) {
var_dump((string)$colors[0]->property);
}
}
SimpleXmlElement::xpath()
will always return an array of SimpleXmlElement
objects. Validate the element count to check if the Xpath expression found a node.
DOM even allows you to fetch the scalar values directly. It will return a empty value if no node matches. The result of DOMXpath::evaluate()
depends on the expression. Location paths return a DOMNodeList
that is traversable with foreach
. A expression that results in a scalar will return the scalar value.
$document = new DOMDocument();
$document->loadXml($xml);
$xpath = new DOMXpath($document);
foreach ($xpath->evaluate('/products/product') as $product) {
$hasColor = $xpath->evaluate('count(properties/prop[propid = 25]) > 0', $product);
if ($hasColor) {
var_dump('Color:', $xpath->evaluate('string(properties/prop[propid = 25]/valueid)', $product));
}
}
Output:
string(6) "Color:"
string(3) "208"
How to check an element exist in XML
You need to check for null
for each of Elements
calls:
if(book != null && book.Element("read") != null && book.Element("read").Element("num") != null) //check the node exist
in C# 6 you can use ?.
operator to make it feel nicer:
if(book?.Element("read")?.Element("num") != null) //check the node exist
Checking if node exist in XML
if(doc.SelectSingleNode("/a/b")!=null)
Check if XML node exists - Loop not finding node if its available
To get the list of nodes, you need to pass just the node name to the method GetElementsByTagName
var node = xmlDoc.GetElementsByTagName("Barcode");
Attached is the screen shot showing it's value in Visual Studio debugger
Also, to add your Xml is not fully right.
I have changed it to make a proper Xml. The Sample I used is
<ProdExtract>
<Product>
<BasicFields>
<ProductCode>000011</ProductCode>
<LongDescription>Product A</LongDescription>
</BasicFields>
</Product>
<Product>
<BasicFields>
<ProductCode>000012</ProductCode>
<LongDescription>Product B</LongDescription>
</BasicFields>
<Barcode>
<Eancode>5391524344444</Eancode>
</Barcode>
</Product>
</ProdExtract>
You can parse your Xml similar to this:
var nodeList = xmlDoc.GetElementsByTagName("Barcode");
if (nodeList != null)
{
if (nodeList.Count > 0)
{
var element = nodeList[0];
string value = element.InnerText;
}
}
The full method to construct an object based on Xml
The logic in this method it to navigate the Xml and pick the required values and set it to the object.
private static Product[] GetDetails(XmlDocument xmlDoc)
{
var result = new List<Product>();
XmlNode tempNode;
var nodeList = xmlDoc.GetElementsByTagName("Product");
foreach(XmlNode node in nodeList)
{
var product = new Product();
tempNode = node.FirstChild; //BasicFields
if (tempNode != null)
{
product.ProductCode = tempNode["ProductCode"].InnerText;
product.LongDescription = tempNode["LongDescription"].InnerText;
}
if (node.ChildNodes.Count > 1)
{
tempNode = node.ChildNodes[1];
if (tempNode != null)
{
tempNode = tempNode.FirstChild; //Eancode
if (tempNode != null)
{
product.Barcode = tempNode.InnerText;
}
}
}
result.Add(product);
}
return result.ToArray();
}
In the above example, Product
is a simple Class to hold the data
class Product
{
public string ProductCode { get; set; }
public string LongDescription { get; set; }
public string Barcode { get; set; }
}
Related Topics
Asp.Net Web Api:Correct Way to Return a 401/Unauthorised Response
How to Calculate Sum (Total) of Datatable Columns Using C#
Regular Expression for Password Validation in C#
Get the Pre-Last Element of a String Split by Spaces
Pass Array into ASP.NET Core Route Query String
How to Loop Through All Fields in an Object in C#
Mongodb C# Exception Cannot Deserialize String from Bsontype Int32
Linq to SQL Left Outer Join Using Lambda Syntax and Joining on 2 Columns (Composite Join Key)
How to Implement Async Task to Fetch Data from Database Using Async and Await
Create a C# Method to Generate Auto Increment Id
Unexpected Character Encountered While Parsing Value
C# How to Check If a Url Exists/Is Valid
How to Set a Cookie on Httpclient'S Httprequestmessage
Restsharp Post Request - Body With X-Www-Form-Urlencoded Values
How to Get the Display Name Attribute of an Enum Member Via MVC Razor Code
How to Provide Success Messages ASP.NET MVC
Smtpexception: Unable to Read Data from the Transport Connection: Net_Io_Connectionclosed