I have the following in some json I have converted from XML:
"ForSaleStatus":{"items":{"item":{"label":"Not For Sale","value":"2"}}}
This was some xml an application generated from a dropdown. I want to convert it to this in C#:
"ForSaleStatus":"2"
Here is the code I have so far:
var xml = i;
var root = XElement.Parse(xml);
// remove ALL empty elements such as <items/>
root.Descendants().Where(e => string.IsNullOrEmpty(e.Value)).Remove();
// convert the node to JSON for easier processing
var json = JsonConvert.SerializeXNode(root);
Can anyone think of a way of converting the json or am I better off going back to the XML and working on that?
The XML looks like this:
<ForSaleStatus>
<items>
<item>
<label>Not For Sale</label>
<value>2</value>
</item>
</items>
</ForSaleStatus>
It would be easier to extract the values you want and just construct the json from that :
var json = JsonConvert.SerializeObject(new Dictionary<string, string>
{
[root.Name.ToString()] = root.XPathSelectElement("items/item/value").Value
});
If that doesn't compile for you, use this older syntax :
var json = JsonConvert.SerializeObject(new Dictionary<string, string>
{
{ root.Name.ToString(), root.XPathSelectElement("items/item/value").Value }
});
Edit: in case you need values from all the items :
var json = JsonConvert.SerializeObject(root
.XPathSelectElements("items/item")
.ToDictionary(
x => x.XPathSelectElement("label").Value,
x => x.XPathSelectElement("value").Value
));
Related
I wanted to convert the JSON data into XML contains the JSON array entries into the same. JSON data which I am converting is as below
{
"userName":[
"user1",
"user2"
],
"referenceNumber":"098784866589157763",
"responseCode":"00",
"responseDesc":"Success."
}
To convert the JSON to XML using below C# code
XmlDocument doc = JsonConvert.DeserializeXmlNode(jsonData, "response");
which is converting JSON to below XML
<response>
<userName>user1</userName>
<userName>user2</userName>
<referenceNumber>098784866589157763</referenceNumber>
<responseCode>00</responseCode>
<responseDesc>Success.</responseDesc>
</response>
but expected output XML is as below
<response>
<userName>
<element>user1</element>
<element>user2</element>
</userName>
<referenceNumber>098784866589157763</referenceNumber>
<responseCode>00</responseCode>
<responseDesc>Success.</responseDesc>
</response>
Is there any way to achieve the same?
If you can use the LINQ to XML, which is elegant way to manipulate XML documents, then
below is one of the ways to achieve the requirement:
XElement root = JsonConvert.DeserializeXNode(jsonData, "response").Root;
// Create elements for userName in new XML
var docFinal = new XDocument(new XElement("response" , new XElement("userName",
from user in root.Descendants("userName") select new XElement("element", user.Value))));
//Add remaining XML Attributs
docFinal.Root.Add(root.Elements()
.Select(x => new XElement(x.Name, x.Value)).Where(x => x.Name != "userName"));
//OUTPUT
//<response>
// <userName>
// <element>user1</element>
// <element>user2</element>
// </userName>
// <referenceNumber>098784866589157763</referenceNumber>
// <responseCode>00</responseCode>
// <responseDesc>Success.</responseDesc>
//</response>
I have an xml file that looks like this
<Root>
<Element1>17890</Element>
<Element2>0001</Element2>
<Element3>123451324A</Element3>
<Element4>1</Element4>
<Element5>ABC</Element5>
<Element6>DEF</Element6>
<Element7>99.10</Element7>
<Element8>GHI</Element8>
<Element9>2014-01-25</Element9>
<Element10>JKL</Element10>
<Element11>737268</Element11>
</Root>
And I have a corresponding class that have all the element names as properties. Let's say I have a collection of all the elements such as
IEnumerable<XElement> elements;
How do I set the property values of the class to the element values from the xml file?
The only thing I have thought of is to loop over elements and make a big switch statement with sections such as
...
case "Element3":
model.Element3 = element.Value;
break;
...
Is there a better solution?
Assuming you already have a class Model with the fields you want to get from the xml:
var elements = XDocument.Load("XMLFile1.xml").Root.Elements();
var model = new Model()
{
Element1 = elements.FirstOrDefault(t => t.Name.LocalName == "Element1"),
Element2 = elements.FirstOrDefault(t => t.Name.LocalName == "Element2"),
};
Another option is to create a dictionary, so you don't need to update your model every time a new tag name is added to the xml file.
var model = new Dictionary<string, string>();
foreach(XElement tag in elements)
{
model[tag.Name.LocalName] = tag.Value;
}
Or using Linq
var model = elements.ToDictionary(e => e.Name.LocalName, e => e.Value);
Finally you can generate a dynamic object directly from the xml. There's an example here: Deserialize XML To Object using Dynamic
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);
}
I have an xml file similar to the following:
<doc>
<file>
<header>
<source>
RNG
</source>
</header>
<body>
<item name="items.names.id1">
<property>propertyvalue1</property>
</item>
<!-- etc -->
<item name="items.names.id100">
<property>propertyvalue100</property>
</item>
<!-- etc -->
<item name="otheritems.names.id100">
<property>propertyvalue100</property>
</item>
</body>
</file>
</doc>
And the following class:
private class Item
{
public string Id;
public string Property;
}
The file has, for example, 100 item entries (labeled 1 to 100 in the name attribute). How can I use Linq Xml to get hold of these nodes and place them a in list of item?
Using Selman22's example, I'm doing the following:
var myList = xDoc.Descendants("item")
.Where(x => x.Attributes("name").ToString().StartsWith("items.names.id"))
.Select(item => new Item
{
Id = (string)item.Attribute("name"),
Name = (string)item.Element("property")
}).ToList();
However, the list is empty. What am I missing here?
Using LINQ to XML:
XDocument xDoc = XDocument.Load(filepath);
var myList = xDoc.Descendants("item").Select(item => new Item {
Id = (string)item.Attribute("name"),
Property = (string)item.Element("property")
}).ToList();
You can use LinqToXml to directly query the XML, or deserialize it and use LINQ to object. If you choose to deserialize I suggest to start from the schema and generate the classes representing your datamodel with xsd.exe. If you don't have the schema of your xml, even xsd.exe can infer one from an example xml file, but you probably need to fine tune the result.
Try this one XElement root = XElement.Parse("your file name");
var items textSegs =(from item in root.Descendants("item")
select item).ToList();
Now iterate over list and store it
The below is a way of getting information from xml using Xdocument.
string input = "<Your xml>";
Xdocument doc = XDocument.Parse(input);
var data = doc.Descendants("item");
List<Items> itemsList = new List<Items>();
foreach(var item in data)
{
string itemname= item.Element("item").Value;
string property = item.Element("property").Value;
itemsList.Add(new item(itemname, property));
}
I'm guessing you want the code given how your question is phrased.. also I'm assuming the real XML is very simplistic as well.
var items = from item in doc.Descendants("item")
select new Item()
{
Id = item.Attributes("name").First().Value,
Property = item.Elements().First().Value,
};
Just ensure that your xml is loaded into doc. You can load the xml in two ways:
// By a string with xml
var doc = XDocument.Parse(aStringWithXml);
// or by loading from uri (file)
var doc = XDocuemnt.Load(aStringWhichIsAFile);
I have a data set that I receive from a service. The data comes in XML format. We are given an XElement object with all the data. The structure of the XML document is very simple. Looks like this:
<root>
<dataPoint>
<id>1</id>
<param1>somedata</param1>
<param2>somedata</param2>
</dataPoint>
<dataPoint>
<id>2</id>
<param1>somedata</param1>
<param2>somedata</param2>
</dataPoint>
</root>
Of course, I have a large number of dataPoints. I also have a list (List) with the id's of dataPoints being displayed in a GUI. What I'd like to have is the dataPoints that ARE NOT displayed on the GUI so I can manipulate only those and not the whole data set.
Thanks
var toDisplay = new List<string>() { "2" };
var xDoc = XElement.Load(.....);
var dPoints = xDoc.Descendants("dataPoint")
.Where(d => !toDisplay.Contains(d.Element("id").Value));
var newXml = new XElement("root",dPoints).ToString();
Here's one way using a mutable dictionary and giving you a dictionary of points and corresponding nodes:
var xml = "<root> \r\n <dataPoint>\r\n <id>1</id>\r\n <param1>somedata</param1>\r\n <param2>so" +
"medata</param2>\r\n </dataPoint>\r\n <dataPoint>\r\n <id>2</id>\r\n <param1>somedata" +
"</param1>\r\n <param2>somedata</param2>\r\n </dataPoint>\r\n</root>";
var doc = XElement.Parse(xml);
var pointsInGui = new List<int> {1, 3, 5};
var dict = doc.Descendants("dataPoint").ToDictionary(e => Convert.ToInt32(e.Element("id").Value));
foreach (var point in pointsInGui) dict.Remove(point);
At this point dict contains 2 => <relevant element>.