I am working with a receipt format that is returned to me as a "saml assertion". This is a known and well defined format, but on my current platform, I don't have access to libraries that can deserialize the xml to the original classes.
I've determined that I will likely need to roll my own classes but given the format of the xml, I don't really know what the C# classes would look like or the definition and tricks needed to get it to deserialize.
The goal is that from the receipt, create a list of C# objects that I can examine. I would like to retain the value in Format, in the Name node as well as the id. In addition, part of what makes this challenging is that Statement consists of both subject and attribute elements. One of the questions I would like to ask the list is, does the list contain a Assertion that has an Attribute node with "Gamma" having the value of 999.
here's the format:
<Assertion>
<Statement>
<Subject>
<Name Format="http://name.com/123/45/ProductName" Id="123">123456</Name>
</Subject>
<Attribute Name="Alpha">
<Value>111</Value>
</Attribute>
<Attribute Name="Gamma">
<Value>22</Value>
</Attribute>
...
<Attribute Name="Delta">
<Value>3</Value>
</Attribute>
</Statement>
</Assertion>
You can use the XML Schema Definition Tool (Xsd.exe) to get your class structure started.
Here's an excellent blog post by Yogesh Joshi that walks through the whole process: http://blogs.msdn.com/b/yojoshi/archive/2011/05/14/xml-serialization-and-deserialization-entity-classes-with-xsd-exe.aspx
As Kon said in the comment, the Attribute nodes should be wrapped in a container element. I haven't found any good way to deserialize a list that also has other elements in it (or attributes, either). You'll probably be forced to have your class implement IXmlSerializable and write more than you would otherwise need to.
Related
Below Example How can Get "Airtel" and "145" Values, because my Client Has given this type XML Response
So How Can I Get both Values
<item item="Campaign name" type="string">Airtel</item>
<item item="Daily Limit" type="number">145</item>
As per the comment, we would need to see the full XML to give you a more complete answer. But you have 3 real options :
XMLReader. Probably not what you want as it's forward only and involves a lot of manual parsing.
XMLDocument. Not a bad option if you only want limited amount of notes and want their values and don't want to deserialize the entire XML doc.
XMLSerializer. Good if you want to deserialize the entire object straight from XML to class without you having to do a heck of a lot.
If you edit your question to include the full XML doc, then I can give you a more complete answer or you can read about your options for parsing XML here : https://dotnetcoretutorials.com/2020/04/23/how-to-parse-xml-in-net-core/
I'm trying to deserialize xml into a complex POCO, and the result of using xsd.exe to make my c# classes from the xsd made some properties string arrays. That might work with my postgres db, but it doesn't work with a mocked dbcontext for unit testing.
An example XML might look like this:
<Car>
<CarWindow>FrontLeft</CarWindow>
<CarWindow>BackLeft</CarWindow>
<OtherFields></OtherFields>
</Car>
So what I want to do is change some of these string arrays, which have a low maxOccurs of 2-4 into dedicated columns. That change will be useful in other ways for this project too. So instead of string[] CarWindow I could have string CarWindow1; string CarWindow2
What I'm missing is a way to specify in the XmlElement attribute a way to map the first, second, etc occurrence of a repeating element. Something like [XmlElement(Occurrence=1)]
I've looked at the XmlElementAttribute documentation and maybe I'm missing it, but I don't see a way to specifically map the nth occurrence of a repeating xml node to one property. Thanks!
I have the following scenarios for output from a web service (the output's type is string, but the content of the string is XML).
When the service didn't succeed the output is:
<root>
<exec_id>2053c884-beec-4c33-af64-bce8c4a8601c</exec_id>
<ERROR_CODE>-13</ERROR_CODE>
<OUTPUT_XML>Policy GO Period is mistaken (Mar 9 2016 8:43PM, Mar 6 2017 11:59PM)</OUTPUT_XML>
</root>
When the service returns something, the response is:
<root>
<exec_id>9a506024-8996-4f17-bcc4-a4616b2c28da</exec_id>
<ERROR_CODE>0</ERROR_CODE>
<OUTPUT_XML>
<root>
<ProposalNo>000334374</ProposalNo>
<InsPremium>225.40</InsPremium>
<InsDuePremium>241.310</InsDuePremium>
<FeesInfo>
<Fee>
<PaymentDate>2016-03-09T16:08:34.613</PaymentDate>
<FeeSum>241.31</FeeSum>
<FeeSumCurCode>BGN</FeeSumCurCode>
<AgencyCode>001</AgencyCode>
</Fee>
</FeesInfo>
<ERROR_MSG>Успешно изпълнена процедура</ERROR_MSG>
</root>
</OUTPUT_XML>
</root>
So, based on this, I created a base class that contains exec_id and ERROR_CODE, because they are common for all responses. Now the problem is OUTPUT_XML, because it's a different object every time so I have a successor class for each method of the service. The problem is when the service returns an error message in the OUTPUT_XML. My question is how to handle this in the best possible way?
Is the service under your control? (Not sure if that's a constraint.)
There are no attributes that will allow out-of-the-box deserialization of the XML in both scenarios above. You could write some custom serialization but that would be overkill.
If the service is yours then you could define a response class and serialize that. If you can serialize it then you can deserialize it. Then in your response XML you have an element for the output and an element for an error message, not one element which may contain either. The contents of XML should be more predictable. That's why we use schemas. But using a class to serialize and deserialize accomplishes the same thing. The XML will be predictable.
You could also get the InnerXml property of the <OUTPUT_XML> node and if it begins with <root> then deserialize that string is a separate XML document. That's logical since that's what they're actually giving you - an XML document as string inside of an XML document.
Or, as was said, if the error code is reliable indicator then you could just read that first.
I'm trying to import XML files into my C# code.
I would like to access these data like a dictionnary element.
Example:
// XML:
<root>
<node>
<value1>
</value1>
<value2>
<properties>
</properties>
</value2>
<randomnode>
<blabla>X</blabla>
</randomnode>
</node>
</root>
// C#:
values["root"]["node"]["randomnode"]["blabla"] == "X" // true
Is there any way to do this?
As far as I've searched, I could only get a dictionnary using XElements, but it was only 2-dimensions and I had to specify names and values as attributes in the XML file.
Thanks for answering!
I suggest you to use dynamic type for this. See here for code. Or here.
I've used sharpSerializer for that. Heres a pretty good walkthrough:
XML Serialization of Generic Dictionary, Multidimensional Array, and Inherited Type, with sharpSerializer .NET
Currently, I'm adding elements to my XmlDocument using XPath notation for which I've written code to that places the element at the proper location in the file. With one exception. I don't know how to make it pay attention to the sequence rules defined in my XSD file.
Is there a way to add an element to an XmlDocument so that is abides by the sequence define in the XSD that governs my XML file?
For example, my xml document should look like:
<rootTag>
<area name="I define an area">
<description>some text here</description>
<point x="1" y="1" />
<point x="2" y="2" />
<point x="3" y="3" />
</area>
</rootTag>
Yet I get, depending on the order in which the user enters values for the child tags above:
<rootTag>
<area name="I define an area">
<point x="1" y="1" />
<point x="2" y="2" />
<point x="3" y="3" />
<description>some text here</description>
</area>
</rootTag>
To correct the above, I create a DataSet (named tempXmlDataset) from the XSD file. I pass the contents of the XmlDocument into tempXmlDataset and things get re-ordered appropriately.
However, my problem is caused by an option for the first child of the XML document. This option is defined in the XSD to allow for "area", "line" or "point" objects. "area" and "line" both have "point" elements as children. But child "point" is not the same as "point" object. So, as you might already realize, tempXmlDataset.ReadXmlSchema(...) creates a "point" table which only has x and y in it. This is by definition of the children for "area" and "line".
So when my code runs tempXmlDataset.ReadXml(...) the attributes for "point" object do not get read in because it sees "point" object as child "point". Here's an example of "point" object:
<rootTag>
<point name="I define a point" x="3" y="3" otherAttributes="">
<description>some text here</description>
</point>
</rootTag>
Since you tagged this C#, I assume you're on the .NET platform. The System.Xml.Schema would be your best friend. For a program that uses the above API to generate XML, that also comes with source code you could use to understand how to solve your issue, I would use the XmlSampleGenerator.
Generating a sample XML requires exactly what you need in terms of constraining the XPath the user may enter at a given point in time. I believe you will have to constrain the XPath you allow based on where you are in the editing process, right from the beginning, otherwise, one single mistake could make the whole approach useless.
If you don't constrain from the beginning, it might be impossible to try to re-order based on an XSD (please read this also in SO)...
use xsd.exe to generate the required code based on the xsd for classes. Don't try to create the dataset for this case. You can then use the generated code together with the XmlSerializer to produce the needed xml files.
http://msdn.microsoft.com/en-us/library/system.xml.serialization.xmlserializer.aspx
Also see:
http://msdn.microsoft.com/en-us/library/ms950721.aspx