how to parse a markup element? - c#

I have a string like this:
var str = "<University id="1396677467961079" name="Oxford"/>";
I want to get value of id, so I could do this:
var id = str.Substring(16, 16);
but it is not a good way to get it. How can I get the value in a safer way?

You can use Linq to XML like this:
var str = "<University id=\"1396677467961079\" name=\"Oxford\"/>";
var el = XElement.Parse(str);
var attr = el.Attribute("id");
var id = attr != null ? attr.Value : string.Empty;
For an overview of Linq to Xml see this link.

Related

How to parse attributes in a collection using newtonsoft

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
};

How to get the Value of XElement

I am parsing through an xml doc and I need to get the value of a Property element. As of right now I have a line of code that returns this:
<Property name="ID" value="thevalueineed"/>
Here is my line of code used.
var ID = from el in linkedinfo.DescendantsAndSelf("Property")
where (string)el.Attribute("name") == "ID"
select el.Attributes("value").ToString();
What would be the next step I am missing that would I get thevalueineed from that Element that I have in var ID?
Just change your select as
select (string)el.Attribute("value")
A working code.
var xDoc = XDocument.Parse(#"<root><Property name=""ID"" value=""thevalueineed""/></root>");
var ID = from el in xDoc.Root.DescendantsAndSelf("Property")
where (string)el.Attribute("name") == "ID"
select (string)el.Attribute("value");
var val = ID.First();
This should work
var ID = from el in linkedinfo.Descendants("Property")
where el.Attribute("name").Value == "ID"
select el.Attribute("value").Value;
I personally like this method when reading XML files but I don't know if it will work with your XML file.
// Create a DataSet
DataSet ds = new DataSet();
// Get the data from the XML file
ds.ReadXml("C:\\myXMLFile.xml");
// Get values
foreach (DataRow dr in ds.Tables[0].Rows)
{
string value = dr["ID"].ToString();
}
select el.Attributes("value")
will return an a type
System.Linq.Enumerable.WhereSelectEnumerableIterator<System.Xml.Linq.XElement,System.Collections.Generic.IEnumerable<System.Xml.Linq.XAttribute>>
try this:
var ID = element.DescendantsAndSelf("Property").Where(x => x.Attribute("name").Value == "id").Select(x => x.Attribute("value")).First();
I would personally use .Value instead of casting to string:
XElement linkedTeethInfo = XElement.Parse(#"<Property name=""ID"" value=""thevalueineed""/>");
var ID = from el in linkedTeethInfo.DescendantsAndSelf("Property")
where el.Attribute("name").Value == "ID"
select el.Attribute("value").Value;
Console.WriteLine("ID: {0}", ID.First());
Created a small fiddle here: https://dotnetfiddle.net/mrSITM

How to extract xml child element

I am trying to figure out the code to extract xml child (I think this is worded correctly) elements. I have searched and tried many samples but cannot find how to drill down to pick out the section I want and return the information I need. Maybe I all I need is someone to define the data I am trying to pull so I can read up on the issue, of course any code would be very helpful and I will figure it out from there. Thanks in advanced for any help!
Here is the xml file. I am trying to run an if statement to find the section named <STATISTICTYPE>PVCAP_CharactersSaved</STATISTICTYPE> and return the <JOBNAME>,<TIMEDELTA>,<VALUESUM>.
<?xml version="1.0" encoding="utf-8"?>
<PVCAPTURESTATISTICCONTAINTER xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<PVCAPTUREJOBSTATISTICS>
<PVCAPTURESTATISTICSUMMARY>
<STATISTICTYPE>PVCAP_CharactersSaved</STATISTICTYPE>
<STATISTICNAME>Characters saved</STATISTICNAME>
<JOBID>24</JOBID>
<JOBNAME>HEAT FILES</JOBNAME>
<TIMEDELTA>422</TIMEDELTA>
<VALUESUM>25432</VALUESUM>
</PVCAPTURESTATISTICSUMMARY>
<PVCAPTURESTATISTICSUMMARY>
<STATISTICTYPE>PVCAP_CharactersSaved_NoMM</STATISTICTYPE>
<STATISTICNAME>Characters saved (no match and merge)</STATISTICNAME>
<JOBID>24</JOBID>
<JOBNAME>HEAT FILES</JOBNAME>
<TIMEDELTA>422</TIMEDELTA>
<VALUESUM>25432</VALUESUM>
</PVCAPTURESTATISTICSUMMARY>
</PVCAPTUREJOBSTATISTICS>
<DOCUMENTCOUNT>762</DOCUMENTCOUNT>
<PAGECOUNT>3194</PAGECOUNT>
<IMAGECOUNT>3194</IMAGECOUNT>
<VERSION>2.0</VERSION>
</PVCAPTURESTATISTICCONTAINTER>
You can use LINQ to XML, particularly the XElement class.
var element = XElement.Parse(xmlStr).Element("PVCAPTUREJOBSTATISTICS")
.Elements("PVCAPTURESTATISTICSUMMARY")
.First(c => c.Element("STATISTICTYPE").Value == "PVCAP_CharactersSaved")
var jobName = element.Element("JOBNAME").Value;
var timeDelta = element.Element("TIMEDELTA").Value;
var valueSum = element.Element("VALUESUM").Value;
You'll want to add in some error handling and whatnot here, but this should get you going in the right direction.
You can do something like this:
XElement res = XElement.Parse(xmlResult);
foreach(var elem in res.Element("PVCAPTUREJOBSTATISTICS").Elements("PVCAPTURESTATISTICSUMMARY"))
{
if (elem.Element("STATISTICTYPE").Value.Equals("PVCAP_CharactersSaved", StringComparison.Ordinal))
{
string jobName = elem.Element("JOBNAME").Value;
string timeDelta = elem.Element("TIMEDELTA").Value;
string valueSum = elem.Element("VALUESUM").Value;
}
}
You can use XDocument and LINQ-to-XML to do that quite easily, for example :
string xml = "your xml content here";
XDocument doc = XDocument.Parse(xml);
//or if you have the xml file instead :
//XDocument doc = XDocument.Load("path_to_xml_file.xml");
var result = doc.Descendants("PVCAPTURESTATISTICSUMMARY")
.Where(o => (string) o.Element("STATISTICTYPE") == "PVCAP_CharactersSaved")
.Select(o => new
{
jobname = (string) o.Element("JOBNAME"),
timedelta = (string) o.Element("TIMEDELTA"),
valuesum = (string) o.Element("VALUESUM")
});
foreach (var r in result)
{
Console.WriteLine(r);
}

How to read and update value of nodes in an XElement

I have an xml document (actually a config file) loaded into an XDocument object, that contains an element like this:
<ScheduledTasks>
<add key="RelativePath" value="..\Scheduler\Tasks"/>
<add key="SearchPauseInSeconds" value="10"/>
<add key="MatrixAccount" value="95755UE93ZEb3fRZUSZ753K9FRS3O9DaDrJxtdiiZnm"/>
<add key="MatrixPassword" value="95755UE93ZEb3fRZUSZ753K9FRS3O9DaDgKrn2e71"/>
</ScheduledTasks>
How can I best retrieve (and update) the value of RelativePath, SeachPauseInseconds etc? They aren't XElements.
TIA.
var attribute =
xDocument.Root.Elements()
.Single(element => element.Attribute("key").Value == "RelativePath")
.Attribute("value");
string oldValue = attribute.Value; // to retrieve
attribute.Value = newValue; // to update
They are attributes. Use XElement.Attribute("attributeName") to get them.
var items = (from i in scheduledTasksElement.Elements("add")
select new
{
KeyAttribute = i.Attribute("key"),
Key = (string)i.Attribute("key"),
ValueAttribute = i.Attribute("value"),
Value = (string)i.Attribute("value")
}).ToList();
As you can see, you can easily cast XAttribute to other types like you can do with XElement.
You can also update the value:
items[0].KeyAttribute.Value = "newValue";
You can, for example, create an extension method that will do it
public static void FindAndReplace(this XDocument doc, string key, string newValue)
{
var elem = doc.Descendants("add")
.FirstOrDefault(d => d.Attribute("key").Value == key);
if (elem != null)
elem.Attribute("value").Value = newValue;
}
and use it like
doc.FindAndReplace("RelativePath", "..\Tasks");

XDocument Descendants and Element always return null values

Hey all i have looked thoroughly through all the questions containing XDocument and while they are all giving an answer to what I'm looking for (mostly namespaces issues) it seems it just won't work for me.
The problem I'm having is that I'm unable to select any value, be it an attribute or element.
Using this XML
I'm trying to retrieve the speaker's fullname.
public void GetEvent()
{
var xdocument = XDocument.Load(#"Shared\techdays2013.xml");
XNamespace xmlns = "http://www.w3.org/2001/XMLSchema-instance";
var data = from c in xdocument.Descendants(xmlns + "speaker")
select c.Element(xmlns + "fullname").Value;
}
You can omit the namespace declaration in your linq statement.
public void GetEvent()
{
var xdocument = XDocument.Load(#"Shared\techdays2013.xml");
//XNamespace xmlns = "http://www.w3.org/2001/XMLSchema-instance";
var data = from c in xdocument.Descendants("speaker")
select c.Element("fullname").Value;
}
You can omit WebClient because you have direct local access to a file. I'm just showing a way to process your file on my machine.
void Main()
{
string p = #"http://events.feed.comportal.be/agenda.aspx?event=TechDays&year=2013&speakerlist=c%7CExperts";
using (var client = new WebClient())
{
string str = client.DownloadString(p);
var xml = XDocument.Parse(str);
var result = xml.Descendants("speaker")
.Select(speaker => GetNameOrDefault(speaker));
//LinqPad specific call
result.Dump();
}
}
public static string GetNameOrDefault(XElement element)
{
var name = element.Element("fullname");
return name != null ? name.Value : "no name";
}
prints:
Bart De Smet
Daniel Pearson
Scott Schnoll
Ilse Van Criekinge
John Craddock
Corey Hynes
Bryon Surace
Jeff Prosise
1) You have to drop the namespace
2) You'll have to query more precisely. All your <speaker> elements inside <speakers> have a fullname but in the next section I spotted <speaker id="94" />
A simple fix (maybe not the best) :
//untested
var data = from c in xdocument.Root.Descendants("speakers").Descendants("speaker")
select c.Element("fullname").Value;
You may want to specify the path more precise:
xdocument.Element("details").Element("tracks").Element("speakers").

Categories