C# get data with name attribute in XML - c#

There are some fields on my xml document which are same value but under different name. I want to select the value of "Error" on this xml document and so want to display "deger2". Also I want to display "deger5" How can I do this?
<?xml version="1.0" encoding="UTF-8"?>
<Database xmlns="http://www.example.com/2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Datas>
<Data name="sMsg" access="private" xsi:type="collection" type="string">
<Value key="Cycle" value="deger1" />
<Value key="Error" value="deger2" />
<Value key="Info" value="deger3" />
<Value key="Jog" />
<Value key="Warning" />
</Data>
<Data name="tTabla" access="private" xsi:type="array" type="tabla" size="1">
<Value key="Cycle" value="deger4" />
<Value key="Error" value="deger5" />
<Value key="Info" value="deger6" />
<Value key="Jog" />
<Value key="Warning" />
</Data>
</Datas>
</Database>

You should take the xml namespace into considiration. Using Linq to Xml
var xDoc = XDocument.Parse(xmlstring); //XDocument.Load(filename)
XNamespace ns = "http://www.example.com/2";
var errors = xDoc.Descendants(ns + "Value") //<-- See the usage of ns
.Where(d => (string)d.Attribute("key") == "Error")
.Select(d => (string)d.Attribute("value"))
.ToList();
EDIT
Is there any way to select like this: select error value where Data name="tTabla"?
var errors = xDoc.Descendants(ns + "Data")
.First(d => (string)d.Attribute("name") == "tTabla")
.Descendants(ns + "Value")
.First(d => (string)d.Attribute("key") == "Error")
.Attribute("value")
.Value;
EDIT2
You can also use XPATH
var nsmgr = new XmlNamespaceManager(xDoc.CreateNavigator().NameTable);
nsmgr.AddNamespace("ns", "http://www.example.com/2");
var errors = xDoc.XPathSelectElement("//ns:Data[#name='tTabla']/ns:Value[#key='Error']", nsmgr)
.Attribute("value")
.Value;

U can also use XPath to select them:
XmlNodeList nodeList = root.SelectNodes("//Data/Value[#key="Error"]");

Related

select childnode in xmlnode

I have this result from an httpGet and i want to extract some values from it.
<?xml version="1.0" encoding="UTF-8"?>
<ns4:endpoint xmlns:ns4="identity.ers.ise.cisco.com" xmlns:ers="ers.ise.cisco.com"
xmlns:xs="http://www.w3.org/2001/XMLSchema" description="Beskriv" id="eed9d9a0-5c8d-11ea-8778-
9e4294fe2fb6" name="1A:1A:1A:1A:1A:1A">
<link rel="self" href="https://10.100.10.10:9060/ers/config/endpoint/eed9d9a0-5c8d-11ea-8778-
9e4294fe2fb6" type="application/xml" />
<customAttributes>
<customAttributes>
<entry>
<key>Changed By API</key>
<value />
</entry>
<entry>
<key>TAG name</key>
<value>TagNavn</value>
</entry>
<entry>
<key>API Change Date</key>
<value>2020-03-02</value>
</entry>
<entry>
<key>API Changed By</key>
<value>Mot</value>
</entry>
</customAttributes>
</customAttributes>
<groupId>aa13bb40-8bff-11e6-996c-525400b48521</groupId>
<identityStore />
<identityStoreId />
<mac>1A:1A:1A:1A:1A:1A</mac>
<portalUser />
<profileId />
<staticGroupAssignment>true</staticGroupAssignment>
<staticProfileAssignment>false</staticProfileAssignment>
</ns4:endpoint>
I can extract the "name" and "description" by using xmlnode.value, but im not sure how to access my custom attributes such as <mac> and <groupid>
Are they regarded as child nodes?
Any help is appreciated.
Something as simple as (using XDocument class from System.Xml.Linq namespace):
// You don't need below line
// XDocument xml = XDocument.Load(#"path to txt file");
var macElement = xml.Descendants().Where(element => element.Name == "mac").FirstOrDefault();
// Similairly for groupid elemnt
var groupidElement = xml.Descendants().Where(element => element.Name == "groupid").FirstOrDefault();
if(macElement != null)
{
// do something with macElement.Value
}
if(groupidElement != null)
{
// do something with groupidElement.Value
}
Also call to xml.Descendants() is reduntant, so you could store it in variable like:
var descendants = xml.Descendants();
and reuse it.

XDocument Descendant Selector using Wildcard?

I have some XML structured like this:
<form>
<section-1>
<item-1>
<value />
</item-1>
<item-2>
<value />
</item-2>
</section-1>
<section-2>
<item-3>
<value />
</item-3>
<item-4>
<value />
</item-4>
</section-2>
</form>
...and want to turn it into something sane like this:
<form>
<items>
<item id="1">
<value/>
</item>
<item id="2">
<value/>
</item>
<item id="3">
<value/>
</item>
<item id="4">
<value/>
</item>
</items>
</form>
I am struggling to turn the old XML into an array or object of values. Once in the new format I'd be able to do the following:
XDocument foo = XDocument.Load(form.xml);
var items = foo.Descendants("item")
.Select(i => new Item
{
value = i.Element("value").Value
});
...but in the current mess the xml is in can I wildcard the descendants selector?
var items = foo.Descendants("item"*)
...or something? I tried to follow this question's answer but failed to adapt it to my purpose.
Ah-ha! It did click in the end. If I leave the descendants selector blank and add in a where statement along the lines of what's in this question's answer
.Where(d => d.Name.ToString().StartsWith("item-"))
Then we get:
XDocument foo = XDocument.Load(form.xml);
var items = foo.Descendants()
.Where(d => d.Name.ToString().StartsWith("item-"))
.Select(i => new Item
{
value = i.Element("value").Value
});
...and I'm now able to iterate through those values while outputting the new XML format. Happiness.

Select in XML to a list

I just want to select the content of user list="default" or user list="otherListName" from a variable.
Like when my variable is equal to default I want to select the content of user list="default". By content I mean:
<list nom="Nom" description="Description" image="no_image.png"/>
And I want this content to be parse into a list
<list nom="" description="" image=""/>
<list nom="" description="" image=""/>
<?xml version="1.0" encoding="utf-8"?>
<database>
<user list="default">
<list nom="Nom" description="Description" image="no_image.png"/>
</user>
<user list="otherListName">
<list nom="" description="" image=""/>
<list nom="" description="" image=""/>
</user>
</database>`
I hope that my question is understandable.
You can use LINQ-to-XML, for example, assuming that doc is an XDocument variable containing the original XML :
var listName = "default";
var result = doc.Root
.Elements("user")
.Where(o => (string)o.Attribute("list") == listName)
.Elements("list");
See live demo in dotnetfiddle :
var raw = #"<?xml version='1.0' encoding='utf-8'?>
<database>
<user list='default'>
<list nom='Nom' description='Description' image='no_image.png'/>
</user>
<user list='otherListName'>
<list nom='' description='' image=''/>
<list nom='' description='' image=''/>
</user>
</database>";
var doc = XDocument.Parse(raw);
var listName = "default";
var result = doc.Root
.Elements("user")
.Where(o => (string)o.Attribute("list") == listName)
.Elements("list");
foreach(var r in result)
{
Console.WriteLine(r.ToString());
}
output : (for listName = "default")
<list nom="Nom" description="Description" image="no_image.png" />

How to remove type in XML while generating?

I have 1000 records in text file. My requirement is to insert data into SQL Server. For that, if I can convert to XML or push to script component also fine.
Source Text file consists in this format...
[{"ID":1,"Name":"test1","State":"AP"},{"ID":2,"Name":"test2","State":"KN"},{"ID":3,"Name":"test3","State":null}]
String json = System.IO.File.ReadAllText(#"C:\t1.txt");
byte[] bytes = Encoding.ASCII.GetBytes();
using (var stream = new MemoryStream(bytes))
{
var quotas = new XmlDictionaryReaderQuotas();
var jasonreader - JsonReaderWriterFactory.CreateJasonReader(stream,quotas);
var xml = XDocument.Load(jsonreader);
xmlDocument xd = new XmlDocument();
using (steamwriter fs = new streamwriter(#"C:\t.xml");
{
fs.write(xml);
}
console.writeLine(xml);
}
Output -
<root type="array"
<item type="object">
<ID type="number">1</ID>
<Name type="string">test1</Name>
<State type="string">AP</State>
</item>
<item type="object">
<root type="array"
<item type="object">
<ID type="number">2</ID>
<Name type="string">test2</Name>
<State type="string">KN</State>
</item>
<item type="object">
<root type="array"
<item type="object">
<ID type="number">3</ID>
<Name type="string">test3</Name>
<State type="string"></State>
</item>
</root>
When am using SSIS XML Source task, am getting columns...
External Columns:
type
text
item_id
Output Columns:
type
text
item_id
Ideally, I should get ID, Name, and State columns. What is the issue? How can I get rid of type in XML?
How about using Linq? (using Json.Net)
var jArr = JArray.Parse(File.ReadAllText(filename));
XElement root = new XElement("root");
foreach(JObject jObj in jArr )
{
root.Add(new XElement("item", jObj.Properties()
.Select(p => new XElement(p.Name,
p.Value.ToString()))
.ToArray()));
}
var xml = root.ToString();
or using more linq
var jArr = JArray.Parse(File.ReadAllText(filename));
XElement root = new XElement("root");
root.Add( jArr.Cast<JObject>()
.Select(jObj => new XElement("item", jObj.Properties()
.Select(p => new XElement(p.Name,
p.Value.ToString()))
.ToArray())));
var xml = root.ToString();

Getting data from xml with specific data name and value key

I want to get data from xml but there are lots of tags, fields and value keys. I couldn't select the value which I want. How can I select the "Error" value from this XML with C#?
<?xml version="1.0" encoding="UTF-8"?>
<Database xmlns="http://www.example.com/2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Datas>
<Data name="sMsg" access="private" xsi:type="collection" type="string">
<Value key="Cycle" value="deger1" />
<Value key="Error" value="deger2" />
<Value key="Info" value="deger3" />
<Value key="Jog" />
<Value key="Warning" />
</Data>
<Data name="tTabla" access="private" xsi:type="array" type="tabla" size="1">
<Field name="dddd" xsi:type="array" type="bool" size="1" />
<Field name="ssss" xsi:type="array" type="bool" size="1" />
<Field name="aaaa" xsi:type="array" type="num" size="1" />
<Field name="rrrr" xsi:type="collection" type="num">
<Value key="Actuel" />
<Value key="Expected" />
</Field>
</Data>
</Datas>
</Database>
You can try this way :
var doc = XDocument.Parse(xml);
XNamespace d = doc.Root.GetDefaultNamespace();
var result = (string)
doc.Descendants(d + "Data")
.Elements(d + "Value")
.FirstOrDefault(o => (string) o.Attribute("key") == "Error")
.Attribute("value");
Console.WriteLine(result);
Try this it returns the XElement with Key equal to Error
XDocument m = XDocument.Load(#"Path");
var res = m.Descendants().Where(x => x.Name.LocalName.Equals("Value") && x.Attribute("key") != null && x.Attribute("key").Value.Equals("Error")).FirstOrDefault();
If there are multiple "Error" values for your attributes, you can do:
IEnumerable<XAttribute> answer = xml.Descendants().Attributes().Where(node => node.Value == "Error");
foreach (var xAttribute in answer)
{
Console.WriteLine(xAttribute.Value);
}
If you only want the first or there is only one:
string answer = xml.Descendants().Attributes().FirstOrDefault(node => node.Value == "Error");
Note FirstOrDefault may yield null if it doesn't find any "Error" values inside your xml.
These queries are done using LINQ To XML, i strongly encourage you to read up.

Categories