JsonConvert.DeserializeXmlNode - must begin with an object - c#

I'm getting a JsonSerializationException calling DeserializeXmlNode() on JSON data that starts with [[ (i.e. it's an array of arrays).
What is the best
way to turn this into XML?
Are there any other JSON schemas that can't be turned into XML?
Update: How the XML should appear is an interesting question. Having an array of arrays means there is no root node (that's an easy one - insert ) but also the set of children nodes have no name. I'm not sure what makes sense here. And this may be a deal killer for using XPath on JSON. So on this part too, any suggestions?
Update 2 - the JSON data:
[["P0010001","NAME","state"],
["4779736","Alabama","01"],
["710231","Alaska","02"],
["6392017","Arizona","04"],
["2915918","Arkansas","05"],
["37253956","California","06"],
["5029196","Colorado","08"],
["3574097","Connecticut","09"],
["897934","Delaware","10"],
["601723","District of Columbia","11"],
["18801310","Florida","12"],
["9687653","Georgia","13"],
["1360301","Hawaii","15"],
["1567582","Idaho","16"],
["12830632","Illinois","17"],
["6483802","Indiana","18"],
["3046355","Iowa","19"],
["2853118","Kansas","20"],
["4339367","Kentucky","21"],
["4533372","Louisiana","22"],
["1328361","Maine","23"],
["5773552","Maryland","24"],
["6547629","Massachusetts","25"],
["9883640","Michigan","26"],
["5303925","Minnesota","27"],
["2967297","Mississippi","28"],
["5988927","Missouri","29"],
["989415","Montana","30"],
["1826341","Nebraska","31"],
["2700551","Nevada","32"],
["1316470","New Hampshire","33"],
["8791894","New Jersey","34"],
["2059179","New Mexico","35"],
["19378102","New York","36"],
["9535483","North Carolina","37"],
["672591","North Dakota","38"],
["11536504","Ohio","39"],
["3751351","Oklahoma","40"],
["3831074","Oregon","41"],
["12702379","Pennsylvania","42"],
["1052567","Rhode Island","44"],
["4625364","South Carolina","45"],
["814180","South Dakota","46"],
["6346105","Tennessee","47"],
["25145561","Texas","48"],
["2763885","Utah","49"],
["625741","Vermont","50"],
["8001024","Virginia","51"],
["6724540","Washington","53"],
["1852994","West Virginia","54"],
["5686986","Wisconsin","55"],
["563626","Wyoming","56"],
["3725789","Puerto Rico","72"]]

I had an array of objects, shaped like:
[{foo:bar}, {foo:bar2}]
...What I did to work around this problem is to wrap the text first like so:
public XmlDocument JsonArrayToXml(string json)
{
var wrappedDocument = string.Format("{{ item: {0} }}", json);
var xDocument = JsonConvert.DeserializeXmlNode(wrappedDocument, "collection");
return xDocument;
}
This does not throw an error. The shape of the XML resembles:
<?xml version="1.0" encoding="UTF-8"?>
<collection>
<item>
<foo>bar</foo>
</item>
<item>
<foo>bar2</foo>
</item>
</collection>

Related

Using XDocument to convert selected node to string

I have the following XML sample.
<?xml version="1.0" encoding="utf-8"?>
<GlobalResponses>
<Filters>
<FilterId>11</FilterId>
<FilterId>5</FilterId>
<FilterId>10</FilterId>
</Filters>
<Responses>
<Response>
<Name>Bob</Name>
</Response>
<Response>
<Name>Jim</Name>
</Response>
<Response>
<Name>Steve</Name>
</Response>
</Responses>
</GlobalResponses>
Using XDocument, how can I get only the <Responses> parent and also child nodes, and convert them to a string variable. I looked at XDocument Elements and Descendants, but by calling oXDocument.Descendants("Responses").ToString(); didn't work.
Do I have to iterate over all of the XElements checking each one and then appending to a string variable ?
Function Descendants returns enumeration of XElement, so you need to select specific element.
If you want to get XML element with all the child nodes, you can use:
// assuming that you only have one tag Responses.
oXDocument.Descendants("Responses").First().ToString();
The result is
<Responses>
<Response>
<Name>Bob</Name>
</Response>
<Response>
<Name>Jim</Name>
</Response>
<Response>
<Name>Steve</Name>
</Response>
</Responses>
If you want to get child nodes and concatenate them to single string you can use
// Extract list of names
var names = doc.Descendants("Responses").Elements("Response").Select(x => x.Value);
// concatenate
var result = string.Join(", ", names);
The result is Bob, Jim, Steve
The Descendants() method takes input the element name and it will return you a collection of nodes and from those you then further need to get the elements you are interested in.
You can use linq with XDocument to extract the information. For example, the following code with extract the Name element value from each Response node and prints out :
var nodes = from response in Doc.Descendants("Response")
select response.Element("Name").Value;
foreach(var node in nodes)
Console.WriteLine(node);
Here above Doc.Descendants("Response") will fetch all the <Response> elements and then we are using response.Element("Name") to fetch the <Element> tag for each <Response> element and then using .Value property we get the value between the tag.
See this working DEMO fiddle.

C# Get Xelement filled using List<T>

I have List with objects. I need get filled XElement blocks used objects of list.
Example:
Code:
var x = new XElement("root");
foreach (var rsltn in rsltnList)
{
x.Add(CreateRsltnXml(rsltn));
}
Xml:
<Root>
<MyXmlOfObject1>...</MyXmlOfObject1>
<MyXmlOfObject2>...</MyXmlOfObject2>
...
<MyXmlOfObjectN>...</MyXmlOfObjectN>
</Root>
Is there a better way to create one final XML without "Root" element or how do I create the XML better using "for" (or other cycle) that return next XML?
Xml:
<MyXmlOfObject1>...</MyXmlOfObject1>
<MyXmlOfObject2>...</MyXmlOfObject2>
...
<MyXmlOfObjectN>...</MyXmlOfObjectN>
Thank you all for the help.
I found a solution to your problem. To get the result I needed I use
z.Add (x.Elements ());
Example:
var z = XElement("MainXml");
z.Add (x.Elements ());
I have a lot of XML type blocks:
<Root>
<MyXmlOfObject1>...</MyXmlOfObject1>
<MyXmlOfObject2>...</MyXmlOfObject2>
...
<MyXmlOfObjectN>...</MyXmlOfObjectN>
</Root>
But I do not need the tag <Root> because tags within the <Root> I need to insert into another XML. Using x.Elements(); command I get all the child elements with no root, which was needed.
Total I get needed result:
<MainXml>
<MainXmlTag1>...</MainXmlTag1>
<MainXmlTag2>...</MainXmlTag2>
<MyXmlOfObject1>...</MyXmlOfObject1>
<MyXmlOfObject2>...</MyXmlOfObject2>
...
<MyXmlOfObjectN>...</MyXmlOfObjectN>
<MainXmlTag4>...</MainXmlTag4>
<MainXmlTagN>...</MainXmlTagN>
</MainXml>
If someone can offer the best solution to insert blocks of XML (XElements) into another XML (XElement) - I will be glad to try your option.

LINQ TO XML retrieving Child Element Value

I have the following XML
<ABC xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://ns.hr-xml.org/2007-04-15">
<ReceiptId>
<IdValue>123</IdValue>
</ReceiptId>
<ClientOrderId>
<IdValue>345</IdValue>
</ClientOrderId>
<AccessPoint>
<Description>My Description</Description>
</AccessPoint>
<ABCStatus>
<Status>Error</Status>
<Details>ERRORS:
Talent is already in an active process for this opening.
</Details>
<StatusDate>2015-08-05</StatusDate>
</ABCStatus>
</ABC>
I am trying to retrieve the element value 345 nested in IdValue and ClientOrderId
I have used the Linq to xml code in C# to retrieve the value with no luck
XDocument XMLResults = XDocument.Parse(sResult);
var sClientOrderID =
from nodeAElem in XMLResults.Root.Elements("ABC")
from nodeA1Elem in nodeAElem.Elements("ClientOrderId")
from nodeA11Elem in nodeA1Elem.Elements("IdValue")
select nodeA11Elem.Value;
also need to retrieve the Status Elements value which is Error for the above xml.
Any help is greatly appreciated
Your XML document is using a namespace, you have to use it in your query to make it work.
Root already brings you to ABC element, so you don't have to call Elements("ABC")
You're looking for single value, so you probably want to use Element instead of Elements.
var ns = (XNamespace)"http://ns.hr-xml.org/2007-04-15";
var sClientOrderID = (int)XMLResults.Root
.Element(ns + "ClientOrderId")
.Element(ns + "IdValue");

how to get the suffix value from xml structure?

I stored the xml structure in xml string like abcd variable.test1,test2,test3 are parts of the xml sructure.how to get suffix values like 1,2,3 from test1,test2,test3?
string abcd="<xmlstruct>
<test1>
<name>testname1</name>
<address>testaddress1</address>
<subject>testsub1<subject>
</test1>
<test2>
<name>testname2</name>
<address>testaddress2</address>
<subject>testsub2<subject>
</test2>
<test3>
<name>testname3</name>
<address>testaddress3</address>
<subject>testsub3<subject>
</test3>
</xmlstruct>";
Ideally, don't structure your XML like that in the first place. It's not a good use of element names. It would be better to use:
<test id="1">
...
</test>
<test id="2">
...
</test>
If these are the result of having separate variables in your original classes, that suggests the variables should probably be a single collection instead.
If you really want to find them though, you could use something like this:
IEnumerable<string> ListSuffixes(XElement container, XName prefix)
{
string localPrefix = prefix.Name.LocalName;
var elements = container.Elements()
.Where(x => x.Name.Namespace == prefix.Name.Namespace
&& x.Name.LocalName
.StartsWith(localPrefix));
foreach (var element in elements)
{
yield return element.Name.LocalName.Substring(localPrefix.Length);
}
}
I'm not entirely sure what you are trying to achieve, but this isn't really how XML is normally used.
To obtain the suffixes (1, 2, 3) from a piece of XML that looks like the above then you could parse the XML, select all children of the xmlstruct element and then use string manipulation.
However an alternative schema would probably be a better idea, like storing the suffixes separately as attributes
<xmlstruct>
<test Suffix="1">
<name>testname1</name>
<address>testaddress1</address>
<subject>testsub1<subject>
</test>
<test Suffix="2">
<name>testname2</name>
<address>testaddress2</address>
<subject>testsub2<subject>
</test>
<test Suffix="3">
<name>testname3</name>
<address>testaddress3</address>
<subject>testsub3<subject>
</test>
</xmlstruct>
Element names shouldn't really be dynamic, the list of allowed element names for a given element should normally belong to a fixed (finite) list
You can try this :
Integer.parseInt(s.replaceAll("[\\D]", ""))
This will also remove non-digits inbetween digits, so "test1test1x" becomes 11.
This works:
var suffices =
XDocument
.Parse(abcd)
.Element("xmlstruct")
.Elements()
.Where(xe => xe.Name.ToString().StartsWith("test"))
.Select(xe => int.Parse(xe.Name.ToString().Substring(4)));
It returns:

When parsing XML with Linq, only one object gets fetched

I'm trying to populate an array with the following xml:
<?xml version=\"1.0\" encoding=\"UTF-8\"?>
<data>
<item>
<date>1307018090</date>
<price>10.4718867</price>
<low>10.38100000</low>
<high>10.49000000</high>
<nicedate>14:39</nicedate>
</item>
<item>
...
</item>
and so on
I'm using this Linq-query, which to me means that It'll create one object per :
var items = from item in doc.Element("data").Descendants()
select new Currency
{
Close = item.Element("price").Value.ToString(),
Date = item.Element("date").Value.ToString(),
Low = item.Element("low").Value.ToString(),
High = item.Element("high").Value.ToString(),
Time = item.Element("nicedate").Value.ToString()
};
And when I foreach through items, only one item gets selected. I'm not very used to Linq so I can't figure out how to properly construct this statement. Any suggestions?
You need to start the Linq-Xml like so
var items =
from item in
doc.Element("data")
.Elements("item")
Descedants() method returns not only children, but also grand-children, grand-grand-children etc. So, the second tag that gets processed by LINQ is your first <item>'s <date> and it isn't processed (I think there should be an exception here, can't check at the moment).
Replace your Descedants() call to Elements("item"), as suggested by #DaveShaw

Categories

Resources