Check If Xml Element Exists

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?

  1. First of all, the path is incorrect. / is the path separator for xml path, not \\.
  2. You should not specify the rootName in the xml path since you already calling the SelectSingleNode function for the root node (xmlDoc.DocumentElement)
  3. The way you identify non-existence node incorrect. SelectSingleNode does not throw an exception if the path does not exist. Instead, it simply returns Nothing.

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 exists

To 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

enter image description here

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



Leave a reply



Submit