How to parse attributes in a collection using newtonsoft - c#

Please see the XML below. Comparable_Sale is a repeating item. I am using new NewtonSoft’s Json parser and I need to be able to get the value of _Description attribute where the _type attribute equals a particular string value such as “GrossBuildingArea” from the element.
I have used the code below to parse property values with newtsonsoft, but I can’t figure out how to get at the attributes.
<COMPARABLE_SALE PropertySequenceIdentifier="3" ProjectName="Villages of Devinshire" ProjectPhaseIdentifier="1" PropertySalesAmount="132500" SalesPricePerGrossLivingAreaAmount="109.32" DataSourceDescription="FMLS, 5559496;DOM 80" DataSourceVerificationDescription="Tax Recs/2ndGen/Deeds" SalesPriceTotalAdjustmentPositiveIndicator="N" SalePriceTotalAdjustmentAmount="-1500" SalesPriceTotalAdjustmentGrossPercent="1.1" SalePriceTotalAdjustmentNetPercent="1.1" AdjustedSalesPriceAmount="131000">
<SALE_PRICE_ADJUSTMENT _Type="GrossBuildingArea"_Description="1,254"/>
<SALE_PRICE_ADJUSTMENT _Type="BasementArea" _Description="1,254 Sq.Ft."/>
<SALE_PRICE_ADJUSTMENT _Type="BasementFinish" _Description="1rr2ba4o"/>
</COMPARABLE_SALE>
This code gets me to the properties, but I can't see how to get at the attributes.
for each item in jobject.Children(Of JObject)()
For Each [property] In item.Children(Of JProperty)()
If [property].Value.Type = JTokenType.[String] Then
Dim newItem = New xmlRootValues()
newItem.Name = [property].Name
newItem.Value = [property].Value.ToString()
lstValues.Add(newItem)
End If
Next
next
Any help in either (C# or VB.net) would be much appreciated.
Thanks,
Chaos

To work with xml use an xml api like XDocument. Here you have an example in C#:
var xml = #"<COMPARABLE_SALE PropertySequenceIdentifier=""3"" ProjectName=""Villages of Devinshire"" ProjectPhaseIdentifier=""1"" PropertySalesAmount=""132500"" SalesPricePerGrossLivingAreaAmount=""109.32"" DataSourceDescription=""FMLS, 5559496;DOM 80"" DataSourceVerificationDescription=""Tax Recs/2ndGen/Deeds"" SalesPriceTotalAdjustmentPositiveIndicator=""N"" SalePriceTotalAdjustmentAmount=""-1500"" SalesPriceTotalAdjustmentGrossPercent=""1.1"" SalePriceTotalAdjustmentNetPercent=""1.1"" AdjustedSalesPriceAmount=""131000"">
<SALE_PRICE_ADJUSTMENT _Type=""GrossBuildingArea"" _Description=""1,254""/>
<SALE_PRICE_ADJUSTMENT _Type=""BasementArea"" _Description=""1,254 Sq.Ft.""/>
<SALE_PRICE_ADJUSTMENT _Type=""BasementFinish"" _Description=""1rr2ba4o""/>
</COMPARABLE_SALE>";
var xDoc = XDocument.Parse(xml);
var description = xDoc.Root.Elements("SALE_PRICE_ADJUSTMENT")
.First(e => e.Attribute("_Type").Value == "GrossBuildingArea")
.Attribute("_Description")
.Value;

In linq to xml you can also use Descendants and foreach to get all values for same element.
var obj = from item in xDoc.Descendants("SALE_PRICE_ADJUSTMENT")
select new
{
_Descr = item.Attribute("_Description").Value,
_Type = item.Attribute("_Type").Value
};

Related

Retrieve processing instructions using XDocument

I have an XML document containing processing instructions. I know that, with the XmlDocument class, you can use
var node = xmlDoc.SelectSingleNode("processing-instruction('xml-stylesheet')") as XmlProcessingInstruction;
but I want to use XDocument. How can I do this?
This is how I access an XML file's nodes with the XDocument class.
However, you'll have to be more specific on what you want to do with it.
XDocument doc = XDocument.Load("filepath");
var node = doc.Nodes().OfType<XElement>().SingleOrDefault(n => n.Name == "node name");
var node_value = node.Value;
var node_descendants = node.Descendants();
UPDATE:
As you may have noticed there's no SelectSingleNode in XDocument, in fact, to retrieve the node you want you'll have to fetch it from the corresponding ienumerable collection, or alternatively from the predefined FirstNode, NextNode, PreviousNode, LastNode, but you cannot apply any filters to those. Therefore the only ways to retrieve ProcessingInstruction nodes are
var pI_nodes = doc.Nodes().OfType<XProcessingInstruction>();
And
var pI_nodes = (from node in doc.Nodes()
where node.NodeType == System.Xml.XmlNodeType.ProcessingInstruction
select node);
If you expect to retrieve several ProcessingInstructions and need to filter these as well, the equivalent to the node name would the Target property
var filtered_pIs = pI_nodes_1.Where(pI => pI.Target == "xml-stylesheet");
And as a final reminder the value of the processing instruction is stored in the Data property.
string pI_value = filtered_pIs.First().Data
Here is one way:
var node = xDoc.Root.Nodes().OfType<XProcessingInstruction>().First();

Selecting a node if the attribute is equal to a predefined string

I'm currently using a loop which gives me a variable, which then needs to be fed into an Xpath method to get me any nodes with an attribute equal to my variable. So far, I've learned that Xpath allows you to select a node from the XML document using
root.SelectNodes("Element[#Attribute='SpecificValue']")
However, I'd like to know if there's a way I can insert a predefined variable where the specific value, so I can grab a different set of nodes with each iteration of my loop.
For example something like this:
string attribValue= "test"
root.SelectNodes("Element[#Attribute = attribValue]")
Use string formatting:
string attribValue = "test";
string expression = String.Format("Element[#Attribute = '{0}']", attribValue);
root.SelectNodes(expression);
Using XML Linq
XDocument doc = new XDocument();
XElement root = (XElement)doc.FirstNode;
string attribValue= "test";
var results = root.Descendants("Element").Where(x => x.Attribute("Attribute").Value == attribValue).ToList();​

Read particular XML

I have this XML:
<palinsesto>
<giorno label="Mer" data="2014/12/31">
<canale description="Premium Cinema" id="KE">
<prg Pod="N" Nettv="N" orafine="06:30" orainizio="06:00" replica="No" primaTv="No">
<durata duratapixel="30">30</durata>
<tipologia>Type</tipologia>
<titolo>evento iniziato ieri</titolo>
<descrizione>--</descrizione>
<audio sottotitoli="No subtitles" audioType="Mono" doppioAudio="One language">Not used</audio>
<parentalRating>LIBERO DA DIVIETI</parentalRating>
<trafficLight/>
<anno>--</anno>
<paese>--</paese>
and i need to read the value in prg class and palinsesto class, i try in this mode but not work
XDocument doc = XDocument.Parse(e.Result);
var canal = doc.Descendants(XName.Get("description", "canale")).FirstOrDefault();
var date = doc.Descendants(XName.Get("data", "giorno")).FirstOrDefault();
var title = doc.Descendants(XName.Get("titolo", "prg")).FirstOrDefault();
return always error
It looks like you've misunderstood names, attributes and elements. It looks like you just want something like:
XDocument doc = XDocument.Parse(e.Result);
var root = doc.Root;
var canal = root.Element("canale").Attribute("description").Value;
var date = root.Element("giorno").Attribute("data").Value;
var title = root.Element("titolo").Value;
However:
Currently none of your first three elements are closed, which would cause the above to fail; it's not clear what your real XML would look like. You should indent it to show the intended structure.
Your date is not represented in the normal way for XML - if you're in control of the XML, it would be better to have a value of 2014-12-31
The above code assumes you just want the first element from the root. If that's not the case, you'll need to give us more information
You do not require this XName overload here - the second parameter is used to provide a namespace, which isn't present in the xml you've provided. I believe you are confusing attributes and xmlns namespaces. In order to obtain the attributes, use .Attributes(), as follows:
var canal = doc.Descendants("canale").Attributes("description").FirstOrDefault();
var date = doc.Descendants("giorno").Attributes("data").FirstOrDefault();
var title = doc.Descendants("prg").Attributes("titolo").FirstOrDefault();

Search for attribute value in xaml file using linq in C#?

I know basic about getting node values from a xml file, but in a complicated xaml file I don't know how to write my linq query.
This is a sample of xaml I'm using:
<Activity something:something = " 2010" x:class = "example"..........>
<x:Members>
<x:Property Name= "aaaaa" Type = "Inargument" />
</x:Members>
<sap:abcdef>1322,2222</sap:abcdef>
<prwab:work sap2010:Annotation.AnnotationText = " I need this value" Active = "False" CreatedOn = "2014-07-09" ID = "123456" DisplayName = "theNameIneed">
<prwab:work.activity>
<prwais:collectingActivity sap2010:Annotation.AnnotationText = "I also need this value" > CreatedOn = "2014-07-09" ID = "1234232" DisplayName = "Ineed2">
<prwais .....>
</prwais>
</prwis:collectingActivity>
</prwab:work.activity>
</prwab:work>
</Activity>
I need to get the data in the lines that contain attribute "sap2010:Annotation.AnnotationText", and the value is going to be the content of sap2010:Annotation.AnnotationText, and key is going to be the attribute "ID" and attribute "displayName" in that line.
Here is the query I have right now, I know it's wrong but I don't know the proper way to write it:
var dataNodes = XElement.Load(file, LoadOptions.None);
Console.WriteLine("Loaded xaml file: " + file);
var dataNodesDictionary = from dataRecord in (dataNodes.Elements("prwab") && dataNodes.Elements("prwais"))//this line is wrong, but I dont know how to write it, since annotation may appears in different elements, and even if I only use "prwab" for testing, i still get nothing
where dataRecord.Attributes("Annotation.AnnotationText") != null
select new DictionaryEntry
{
Key = dataRecord.Attribute("DisplayName").Value.ToString() + "|" + dataRecord.Attribute("ID").Value.ToString(),
Value = dataRecord.Attribute("Annotation.AnnotationText").Value.ToString(),
};
Can some one help me please, thanks.
First find all elements that have the attribute. Then pull the attribute values.
// Name of the attributes we are looking
string ns = "http://schemas.microsoft.com/netfx/2010/xaml/activities/presentation";
XName name = XName.Get("Annotation.AnnotationText", ns);
XDocument doc = XDocument.Load("XMLFile1.xml");
var q = doc.Descendants().Where(e => e.Attribute(name) != null)
.Select(e => new DictionaryEntry { Key = e.Attribute("ID").Value, Value = e.Attribute(name).Value });
SIDE NOTE: In the future please paste in valid XML so it is easier for others to reproduce the issue.
Since this is XAML, you'll have a problem:
The attribute you're looking for can be written using a tag:
<prwab:work sap2010:Annotation.AnnotationText="I need this value">
...
</prwab:work>
This is equivalent to:
<prwab:work>
<sap2010:Annotation.AnnotationText>
I need this value
</sap2010:Annotation.AnnotationText>
...
</prwab:work>
So if you need a reliable way to read that, you should use the XamlReader class (the one from the System.Xaml namespace - not the one from System.Windows.Markup). It works in a similar way to XmlReader, but normalizes the XAML it presents to you.
It won't be as straightforward as a linq query, but will be more reliable.

Linq to XML dynamic XML Decendants

I'm parsing a lot of XML files using Linq to XML synatx, everything works when I try to access top level elements
var indexroot = (from element in prodcutDocument.Root.Descendants("indexroot")
select new
{
model = (string)element.Element("MODEL"),
}).FirstOrDefault()
The problem occurs when I need to access lower level childs of that document I tried:
var indexroot = (from element in prodcutDocument.Root.Descendants("indexroot")
select new
{
ddName = (string)element.Descendants("DD_NAME").Elements("name").First();
}).FirstOrDefault()
and
var indexroot = (from element in prodcutDocument.Root.Descendants("indexroot").Descendants("DD_NAME")
select new
{
ddName = (string)element.Element("name")
}).FirstOrDefault();
Sadly none of that works and i get same error "Sequence contains no elements". And one more thing sometimes the XML document contains those tags and sometimes not is something like this enough for handling this case?
var indexroot = (from element in prodcutDocument.Root.Descendants("indexroot").Descendants("DD_NAME")
select new
{
ddName = (string)element.Element("name") ?? "-"
}).FirstOrDefault();
Edit:
I don't think is possible to paste short version of XML that would be simple, so here's full version: http://pastebin.com/uDkP3rnR and for the code example:
XDocument prodcutDocument = XDocument.Load(this.ServerPATHData + file);
var indexroot = (from element in prodcutDocument.Root.Descendants("indexroot")
select new
{
modelis = (string)element.Element("MODELIS"),
T2918_0 = (string)element.Descendants("dd_DARBINIS_GRAFIKAS_SPEC").First()
}).FirstOrDefault();
writeTxt.WriteLine("modelis: " + indexroot.modelis);
writeTxt.WriteLine("T2979_0" + indexroot.T2918_0);
In examining the sample XML that you posted on PasteBin, it appears to me that the elements that you mention appear only once. To access them, you can simply specify a path to each as follows:
XElement indexroot = document.Root.Element("indexroot");
XElement modelis = indexroot.Element("MODELIS");
XElement dd_dgs = indexroot.Element("dd_DARBINIS_GRAFIKAS_SPEC");
XElement voltageuv = dd_dgs.Element("VoltageUV");
string t2979_0 = (string)voltageuv.Element("T2979_0");
string t2861_60 = (string)voltageuv.Element("T2861_60");
string t2757_121 = (string)voltageuv.Element("T2757_121");
(Note that you may need to check for null if there is a chance that any of the elements you are trying to access may not be present. Without doing so, you'll encounter a NullReferenceException.)
Here is a snippet of the XML that you posted to give context to the above code:
<?xml version='1.0' encoding='UTF-8' standalone='no'?>
<PDB>
<indexroot>
<ed_BENDRA_MAKS_SUV_GALIA>1.45</ed_BENDRA_MAKS_SUV_GALIA>
<ed_BENDRA_MAKS_SROVE>6.48</ed_BENDRA_MAKS_SROVE>
<TIPAS>1</TIPAS>
<MODELIS>RIS 2500 HW EC 3.0</MODELIS>
<dd_DARBINIS_GRAFIKAS_SPEC>
<VoltageUV>
<T2979_0>229,42</T2979_0>
<T2861_60>227,98</T2861_60>
<T2757_121>228,97</T2757_121>
</VoltageUV>
<CurrentIA>
<T2979_0>2,56</T2979_0>
<T2861_60>2,63</T2861_60>
<T2757_121>2,72</T2757_121>
</CurrentIA>
</dd_DARBINIS_GRAFIKAS_SPEC>
</indexroot>
</PDB>
You can just change:
element.Descendants("dd_DARBINIS_GRAFIKAS_SPEC").First()
to this:
element.Descendants("dd_DARBINIS_GRAFIKAS_SPEC").FirstOrDefault() ?? "-"

Categories