get decendents in XML where specific element contains value - c#

<?xml version="1.0" encoding="utf-8" ?>
<Licenses>
<License>
<LicenseType>Temporary License</LicenseType>
<BundleType>Line</BundleType>
<Features>
<Feature>
<Value>Full</Value>
<Status>Full Access</Status>
<AccessLevel>Full</AccessLevel>
</Feature>
<Feature>
<Name>EnhancedUserAccounts</Name>
<LocalisedName>Enhanced User Accounts</LocalisedName>
<Value>Full</Value>
<Status>Full Access</Status>
<AccessLevel>Full</AccessLevel>
</Feature>
</Features>
</License>
<License>
<LicenseType>Temporary License</LicenseType>
<BundleType>Line</BundleType>
<Features>
<Feature>
<Value>Full</Value>
<Status>Full Access</Status>
<AccessLevel>Full</AccessLevel>
</Feature>
<Feature>
<Name>EnhancedUserAccounts</Name>
<LocalisedName>Enhanced User Accounts</LocalisedName>
<Value>Full</Value>
<Status>Full Access</Status>
<AccessLevel>Full</AccessLevel>
</Feature>
</Features>
</License>
</Licenses>
How to read the feature list into to IEnumerable if my BundleType = line

You can do this easily using XDocument
var xDocument = XDocument.Parse(XML)
or
var xDocument = XDocuemnt.Load(FilePath)
then:
xDocument.Descendants("LicenseType")
Which will get all nodes that descend from LicenseType
To test for that BundleType element you could do something like:
nodes.Where(n=>n.Element("BundleType") == "Line").Decesendants("Features")
which will get all Features where <BundleType> of the parent is "Line"
EDIT: As per comments, to get all features:
xDocument.Desecendants("Features")
That will get all <Feature> nodes under the <Features> Element

Use following based on the xml I updated on your posting :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication70
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
XDocument doc = XDocument.Load(FILENAME);
var results = doc.Descendants("License").Where(x => (string)x.Element("BundleType") == "Line")
.Select(x => x.Descendants("Feature").ToList()).ToList();
}
}
}

Related

How do I get SOAP xml file data using LINQ and display it in a form's text box? C#

How do I do it?
This is the SOAP XML file
<soapenv:Envelope xmlns:soapenv="http://www.w3.org/2001/12/soap-envelope" soapenv:encodingStyle="http://www.w3.org/2001/12/soap-encoding" >
<soapenv:Body xmlns:lle="http://www.aab.org/logevents" >
<lle:Events>
<lle:eventid>ID1</lle:eventid>
<lle:tweet>
<lle:text>This is some tweet in my day</lle:text>
<lle:location>
<lle:lat>66</lle:lat>
<lle:long>77</lle:long>
</lle:location>
<lle:datetimestamp>datetimestamp</lle:datetimestamp>
</lle:tweet>
</lle:Events>
</soapenv:Body>
</soapenv:Envelope>
And this is my C# code, it doesn't display anything in the text box, I have tried adding the "lle:" in front of "Event" and its Descendants like:
.Descendants("lle:Events")
select events.Element("lle:eventid").Value;
but apparently it doesn't work, and there's lots of errors, so I changed it back
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Xml.Linq;
namespace Xmltest
{
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
}
private void Form2_Load(object sender, EventArgs e)
{
XDocument xmlDocument = new XDocument();
IEnumerable<string> id = from events in XDocument.Load(#"C:\Users\Jack\source\repos\xmltest\Xmltest\XmlFile.xml")
.Descendants("Events")
select events.Element("eventid").Value;
this.txtBox1.Text = id.FirstOrDefault();
}
}
}
but it worked perfectly fine with normal xml file below
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<Customers>
<Customer ID="101">
<Name>Robert</Name>
<Mobile>9820098200</Mobile>
<Location>Bangladesh</Location>
<Address>XYZ</Address>
</Customer>
<Customer ID="102">
<Name>Kate</Name>
<Mobile>983452342</Mobile>
<Location>Japan</Location>
<Address>ABC</Address>
</Customer>
<Customer ID="103">
<Name>Catherine</Name>
<Mobile>123456785</Mobile>
<Location> London</Location>
<Address>CDE</Address>
</Customer>
<Customer ID="10004">
<Name>Richard</Name>
<Mobile>899990012</Mobile>
<Location>France</Location>
<Address>MNO</Address>
</Customer>
</Customers>
I believe that's because you are using strings to refer to element. You should use XName, e.g. instead of "Events" or "eventid" use:
var events = XName.Get("Events", "http://www.aab.org/logevents");
var eventId = XName.Get("eventid", "http://www.aab.org/logevents");
You can use below powershell snippet for a quick test:
$x = [System.Xml.Linq.XDocument]::Load("C:\Users\Jack\source\repos\xmltest\Xmltest\XmlFile.xml")
$evtName = [System.Xml.Linq.XName]::Get("Events", "http://www.aab.org/logevents")
$idName = [System.Xml.Linq.XName]::Get("eventid", "http://www.aab.org/logevents")
$x.Descendants($evtName).Element($idName).Value | Write-Host
You have to handle the Xml Namespace. You can do this by querying with XName, instead of with a string:
using System;
using System.Linq;
using System.Xml.Linq;
public class Program
{
public static void Main()
{
var inXml = #"<soapenv:Envelope xmlns:soapenv=""http://www.w3.org/2001/12/soap-envelope"" soapenv:encodingStyle=""http://www.w3.org/2001/12/soap-encoding"" >
<soapenv:Body xmlns:lle=""http://www.aab.org/logevents"" >
<lle:Events>
<lle:eventid>ID1</lle:eventid>
<lle:tweet>
<lle:text>This is some tweet in my day</lle:text>
<lle:location>
<lle:lat>66</lle:lat>
<lle:long>77</lle:long>
</lle:location>
<lle:datetimestamp>datetimestamp</lle:datetimestamp>
</lle:tweet>
</lle:Events>
</soapenv:Body>
</soapenv:Envelope>";
var eventIdsXName = XName.Get("eventid", "http://www.aab.org/logevents");
var eventIds = XDocument.Parse(inXml)
.Descendants(eventIdsXName)
.Select(i => i.Value);
foreach(var eventId in eventIds){
Console.WriteLine($"Value: {eventId}");
}
}
}
Output:
Value: ID1
See:
https://dotnetfiddle.net/IEdwz1

Modify soap response conditionally

I wanted to modify/delete node from the soap response xml on the basis of Country passed as a parameter, here in this xml I wanted to delete node if the Country=”US”.
I tried using the below code but it did not select nodes.
XDocument doc = XDocument.Parse(“XMLString”));
XNamespace xmlns = " http://schemas.xmlsoap.org/soap/envelope/";
var addressNode = doc.Descendants(xmlns + " AddressData").Elements(xmlns + " Country");
Can anybody suggest approach to delete node on the basis of Country.
Sample Xml:
<?xml version="1.0" encoding="UTF-8"?>
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<GetAddressDataRs xmlns="xyz.com/Services/Schemas/ Address /v1" xmlns:cm="xyz.com/Services/Schemas/Common/v1" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="xyz.com/Services/Schemas/Address /Schemas.xsd">
<AddressData>
<Id xsi:type="xsd:string">1</Id>
<Add1>ABCDEFG</Add1>
<Add2>XYZABV</Add2>
<City>Las Vegas</City>
<Country>US</Country>
</AddressData>
<AddressData>
<Id xsi:type="xsd:string">1</Id>
<Add1>ABCDEFG</Add1>
<Add2>XYZABV</Add2>
<City>Phoenix</City>
<Country>US</Country>
</AddressData>
<AddressData>
<Id xsi:type="xsd:string">1</Id>
<Add1>ABCDEFG</Add1>
<Add2>XYZABV</Add2>
<City>Kansas City</City>
<Country>US</Country>
</AddressData>
<AddressData>
<Id xsi:type="xsd:string">1</Id>
<Add1>ABCDEFG</Add1>
<Add2>XYZABV</Add2>
<City>Sydney</City>
<Country>Australia</Country>
</AddressData>
<AddressData>
<Id xsi:type="xsd:string">1</Id>
<Add1>ABCDEFG</Add1>
<Add2>XYZABV</Add2>
<City>Townsville</City>
<Country>Australia</Country>
</AddressData>
</GetAddressDataRs>
</s:Body>
</s:Envelope>
Try following xml linq :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Xml;
using System.Xml.Linq ;
namespace ConsoleApplication91
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
XDocument doc = XDocument.Load(FILENAME);
var usa = doc.Descendants().Where(x => x.Name.LocalName == "AddressData").Where(x => x.Elements().Any(y => (y.Name.LocalName == "Country") && ((string)y == "US"))).FirstOrDefault();
}
}
}

XML to Linq C# retrieve entries from XML

I need to to the following task:
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<Eintrag>
<Kunde>
<Email> example#test.de </Email>
<Kundennummer>1234567 </Kundennummer>
</Kunde>
<Kunde>
<Email> example1#test.de </Email>
<Kundennummer>1234569 </Kundennummer>
</Kunde>
</Eintrag>
I need to save Email and Kundennummer of each Kunde in a String.
Can you please tell me how to do it?
Try following :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication62
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
XDocument doc = XDocument.Load(FILENAME);
var results = doc.Descendants("Kunde").Select(x => new
{
email = (string)x.Element("Email"),
num = (string)x.Element("Kundennummer")
}).ToList();
}
}
}

XML C# Parse - Complex

I have been on google for a while but am just stumped. I need to parse xml of this nature. I can't seem to skip to elements in the middle, e.g. Folder. I have limited the xml as there were many 'Folder' elements. Any guidance would be appreciated. I was after the FolderID element's attribute ID.
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header>
<h:ServerVersionInfo MajorVersion="14"
MinorVersion="1"
MajorBuildNumber="225"
MinorBuildNumber="46"
Version="Exchange2010_SP1"
xmlns:h="http://schemas.microsoft.com/exchange/services/2006/types"
xmlns="http://schemas.microsoft.com/exchange/services/2006/types"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema" />
</s:Header>
<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<m:GetFolderResponse xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages"
xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types">
<m:ResponseMessages>
<m:GetFolderResponseMessage ResponseClass="Success">
<m:ResponseCode>NoError</m:ResponseCode>
<m:Folders>
<t:Folder>
<t:FolderId Id="AAMkADk5MmY1ZThmLTM2MzAtNGVh" ChangeKey="AQAAABYAAACSe/NBrSZiQKqHx8yL+lIRAAAA1EWM" />
<t:ParentFolderId Id="AAMkADk5MmY1ZThmLTM2MzAtNGVh" ChangeKey="AQAAAA==" />
<t:DisplayName>Top of Information Store</t:DisplayName>
<t:TotalCount>0</t:TotalCount>
<t:ChildFolderCount>15</t:ChildFolderCount>
<t:EffectiveRights>
<t:CreateAssociated>true</t:CreateAssociated>
<t:CreateContents>true</t:CreateContents>
<t:CreateHierarchy>true</t:CreateHierarchy>
<t:Delete>true</t:Delete>
<t:Modify>true</t:Modify>
<t:Read>true</t:Read>
<t:ViewPrivateItems>true</t:ViewPrivateItems>
</t:EffectiveRights>
<t:PermissionSet>
<t:Permissions>
<t:Permission>
<t:UserId>
<t:DistinguishedUser>Default</t:DistinguishedUser>
</t:UserId>
<t:CanCreateItems>false</t:CanCreateItems>
<t:CanCreateSubFolders>false</t:CanCreateSubFolders>
<t:IsFolderOwner>false</t:IsFolderOwner>
<t:IsFolderVisible>false</t:IsFolderVisible>
<t:IsFolderContact>false</t:IsFolderContact>
<t:EditItems>None</t:EditItems>
<t:DeleteItems>None</t:DeleteItems>
<t:ReadItems>None</t:ReadItems>
<t:PermissionLevel>None</t:PermissionLevel>
</t:Permission>
<t:Permission>
<t:UserId>
<t:DistinguishedUser>Anonymous</t:DistinguishedUser>
</t:UserId>
<t:CanCreateItems>false</t:CanCreateItems>
<t:CanCreateSubFolders>false</t:CanCreateSubFolders>
<t:IsFolderOwner>false</t:IsFolderOwner>
<t:IsFolderVisible>false</t:IsFolderVisible>
<t:IsFolderContact>false</t:IsFolderContact>
<t:EditItems>None</t:EditItems>
<t:DeleteItems>None</t:DeleteItems>
<t:ReadItems>None</t:ReadItems>
<t:PermissionLevel>None</t:PermissionLevel>
</t:Permission>
</t:Permissions>
</t:PermissionSet>
<t:UnreadCount>0</t:UnreadCount>
</t:Folder>
</m:Folders>
</m:GetFolderResponseMessage>
</m:ResponseMessages>
</m:GetFolderResponse>
</s:Body>
</s:Envelope>
LINQ to XML is the best .NET XML Parsing API.
See
https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/linq/xdocument-class-overview
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
namespace ConsoleApp12
{
class Program
{
static void Main(string[] args)
{
var doc = XDocument.Load(#"c:\temp\foo.xml");
var ns = (XNamespace)"http://schemas.microsoft.com/exchange/services/2006/types";
var folders = doc.Descendants(ns + "Folder");
foreach (var e in folders)
{
var folderId = e.Element(ns + "FolderId").Attribute("Id").Value;
Console.WriteLine(folderId);
}
Console.WriteLine("Hit any key to exit.");
Console.ReadKey();
}
}
}
You should learn about serlialization. It's very easy to convert an XML to and from a object in C#. https://www.codeproject.com/Articles/483055/XML-Serialization-and-Deserialization-Part
That said, this will get you the data you're after. It's not very reusable and won't help you with any xml files other than ones with one instance of that attribute, but it's what you're after so here you go.
string FolderId;
string ChangeKey;
using (StreamReader sr = new StreamReader("c:\\myfile.xml"))
{
string line;
while ((line = sr.ReadLine()) != null)
{
if (line.Contains("<t:FolderId Id="))
{
try
{
var lineArray = line.Split('\"');
FolderId = lineArray[1];
ChangeKey = lineArray[3];
}
catch
{
// handle exception
}
}
}
}
You can use the XSD.exe to create a schema class. and then using XML deserializer, you can deserialize/parse xml to object
Using xml linq
XDocument doc = XDocument.Load(FILENAME);
List<XElement> folders = doc.Descendants().Where(x => x.Name.LocalName == "Folder").ToList();
XNamespace tNs = folders.FirstOrDefault().GetNamespaceOfPrefix("t");
XElement id_AAMkADk5MmY1ZThmLTM2MzAtNGVh = folders.Where(x => (string)x.Element(tNs + "FolderId").Attribute("Id") == "AAMkADk5MmY1ZThmLTM2MzAtNGVh").FirstOrDefault();

cannot get node by using selectSingleNode method

my xml file is like below:
<?xml version="1.0"?>
<UpdateInboundim613Response xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" status="SUCCESS" message="Success" schemaRevisionDate="2016-07-19" schemaRevisionLevel="0" returnCode="0" xmlns="http://schemas.hp.com/SM/7">
<model>
<keys>
<TransactionID type="String">E-InHPSXIM1089779</TransactionID>
</keys>
<instance uniquequery="TransactionID="E-InHPSXIM1089779"" recordid="E-InHPSXIM1089779">
<TransactionDetailedTrace xsi:nil="true" />
<TransactionMessage type="Array">
<TransactionMessage type="String" />
</TransactionMessage>
<OVSCSolutionDescription type="Array">
<OVSCSolutionDescription type="String">Issue: EL-BANK OUTSIDE WAREHOUSE EGYPT IMEA[2702]Interface[[E1 0/0/0]]|Router|ELBKCE1GW /pg-h-pg1252-256675160|143.34.213.18|Down Solution: As per update from Mai Shrief that the site has been suspended on 30th June. So no need of any investigation. Resolved By: BT NOC</OVSCSolutionDescription>
</OVSCSolutionDescription>
<OVSCTicketID type="String">E-IM004004076</OVSCTicketID>
<RIMSImpact xsi:nil="true" />
<attachments />
</instance>
</model>
<messages>
<message type="String" xmlns="http://schemas.hp.com/SM/7/Common">TransactionStatusDetail in $L.file is:IM Ticket: E-IM004004076 is valid for Update Subtype: Resolve</message>
</messages>
</UpdateInboundim613Response>
but my code cannot get value of element "OVSCTicketID":
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(#"C:\zzx\Project\SM\R5.1\Harness\InBound.xml");
XmlNode sigNode = xmlDoc.SelectSingleNode("/UpdateInboundim613Response/model/instance/OVSCTicketID");
if (sigNode != null)
{
Console.WriteLine(sigNode.InnerText);
}
can you please tell me what's the problem and how to fix it?
Your Xml document uses the default namespace "http://schemas.hp.com/SM/7". You need to use the XmlNamespaceManager to select that node under this namespace.
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(#"C:\zzx\Project\SM\R5.1\Harness\InBound.xml");
var namespaceManager = new XmlNamespaceManager(xmlDoc.NameTable);
namespaceManager.AddNamespace("ns", "http://schemas.hp.com/SM/7");
XmlNode sigNode = xmlDoc.SelectSingleNode("//ns:UpdateInboundim613Response//ns:model//ns:instance//ns:OVSCTicketID",namespaceManager);
if (sigNode != null)
{
Console.WriteLine(sigNode.InnerText);
}
Above code should work fine.
Using xml linq
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
XDocument doc = XDocument.Load(FILENAME);
XNamespace defaultNs = ((XElement)doc.FirstNode).GetDefaultNamespace();
string ovsCTicketID = (string)doc.Descendants(defaultNs + "OVSCTicketID").FirstOrDefault();
}
}
}

Categories