I am having trouble with deserializing a XML into C# Model. I am pulling that XML from external API, so i have no control over it. It has multiple "InnerText" nodes, that serialized cant deserialize correctly(last one wins, orhers are lost).
I`ve already fixed this using XmlDocument Class, but i need to do it with model instead.
The XML i am trying to deserialize:
<root>
<passage>
<hlword>Test</hlword>
your Internet.....
<hlword>test</hlword>
from Ookla.
</passage>
</root>
C# Classes:
[XmlRoot(ElementName = "passage")]
public class Passage
{
[XmlElement(ElementName = "hlword")]
public List<string> Hlword { get; set; }
[XmlText]
public string InnerText { get; set; }
}
[XmlRoot(ElementName = "root")]
public class Root
{
[XmlElement(ElementName = "passage")]
public List<Passage> Passage { get; set; }
[XmlText]
public string InnerText { get; set; }
}
From example above, i need to extract: "Test your internet..... test from Ookla", Instead I am getting List of Passage class with 2 Hlwords (inner text "test") and inner text on Root class "from Ookla". All the text after elements is ommited.
Try reading the innertext using XmlDocument
var doc = new XmlDocument();
doc.LoadXml(xmlString);
var text = doc.SelectSingleNode("root/passage").InnerText;
Related
I have a large number of XML files that I need to perform de-serialization on. These files have varying root names (over 250). I'm trying to pass the root attribute name through XmlSerializer before accessing the XML class to retrieve my data. Here is what I have but I'm still getting an error that the root name was expected although the XmlElement class is passing the attribute to the XmlSerializer class.
The method used to retrieve the file:
string strXmlDoc = path;
XmlDocument objXmlDoc = new XmlDocument();
objXmlDoc.Load(strXmlDoc);
XmlElement objRootElem = objXmlDoc.DocumentElement;
XmlSerializer xmlSerial = new XmlSerializer(typeof(XMLFile), new XmlRootAttribute(objRootElem.ToString()));
StreamReader sr = new StreamReader(path);
XMLFile entity = xmlSerial.Deserialize(sr) as XMLFile;
The XML classes file:
[Serializable]
//[XmlRoot("randomname")] Removed this line since I'm getting the XmlRoot attribute in the XmlSerializer line.
public class XMLFile
{
[System.Xml.Serialization.XmlElement("RECORD")]
public RECORD RECORD { get; set; }
}
[Serializable]
public class RECORD
{
[XmlElement("BK01")]
public Record Bk01 { get; set; }
[XmlElement("BK02")]
public Record Bk02 { get; set; }
}
[Serializable]
public class Record
{
[XmlAttribute("Value")]
public string Value { get; set; }
}
Change this:
XmlSerializer xmlSerial =
new XmlSerializer(typeof(XMLFile), new XmlRootAttribute(objRootElem.ToString()));
to this:
XmlSerializer xmlSerial =
new XmlSerializer(typeof(XMLFile), new XmlRootAttribute(objRootElem.Name));
^^^
XmlElement.ToString() will always return System.Xml.XmlElement, which is not what you want.
I'm serializing a class into an XML document and I want to understand how to add a custom attribute to multiple fields of the class. I know we can use
[XMLAttribute(AttributeName="CustomAttribute"] to add a custom attribute to a single node of an XML document, but I can't figure out how to add a custom attribute to multiple nodes.
My class is as follows:
[XmlRoot(ElementName = "customer")]
public class Customer
{
[XmlElement(ElementName = "cust_id")]
public string CustomerId {get; set;}
[XmlElement(ElementName = "cust_name")]
public string CustomerName {get; set; }
[XmlElement(ElementName = "cust_phone")]
public string CustomerPhone {get; set; }
[XmlElement(ElementName = "cust_email")]
public string CustomerEmail {get; set; }
}
And, I'm using the following code to serialize the class into XML:
var xmlSerializer = new XmlSerializer(toSerialize.GetType());
using (var textWriter = new StringWriter())
{
xmlSerializer.Serialize(textWriter, toSerialize);
return textWriter.ToString();
}
After serializing the above class, I get the following XML:
<customer>
<cust_id>1</cust_id>
<cust_name>John</cust_name>
<cust_phone>12345678</cust_phone>
<cust_email>john#gmail.com</cust_email>
</customer>
Now, in case if any of the fields of the customer class are null, I want to mark the respective XML nodes as IsNull = "TRUE". For Example:
<customer>
<cust_id>1</cust_id>
<cust_name>John</cust_name>
<cust_phone IsNull = "TRUE" />
<cust_email IsNull = "TRUE" />
</customer>
How can we serialize a class into XML like above so that custom attributes are set for multiple nodes of an XML document?
Thank You,
I have an XML and I load it in an class.
This is my XML
<out_policySystem xmlns:msl="http://www.ibm.com/xmlmap" xmlns:io="" xmlns:xs4xs="http://www.w3.org/2001/XMLSchema">
<BGBAResultadoOperacion>
<Severidad>OK</Severidad>
</BGBAResultadoOperacion>
<permiteOperar>true</permiteOperar>
<Lista xmlns:ns0=\"http://CalypsoPolicySystem_lib/service\">
<Codigo>ODM-006</Codigo>
<Descripcion>Aviso</Descripcion>
<DescripcionTecnica>XXXX</DescripcionTecnica>
</Lista>
</out_policySystem>
I have define my classes like this.
[XmlRoot(ElementName = "out_policySystem")]
public partial class output_policySystem
{
public BGBAResultadoOperacion BGBAResultadoOperacion { get; set; }
public bool permiteOperar { get; set; }
public List[] Lista { get; set; }
}
public partial class BGBAResultadoOperacion
{
public string Severidad { get; set; }
}
public partial class List
{
public string Codigo { get; set; }
public string Descripcion { get; set; }
public string DescripcionTecnica { get; set; }
}
I read this like this.
XmlNodeList elemlist = xDoc.GetElementsByTagName("out_policySystem");
string result = elemlist[0].InnerXml;
XmlSerializer serializer = new XmlSerializer(typeof(BGBAResultadoOperacion));
using (StringReader reader = new StringReader(result))
{
result = (BGBAResultadoOperacion)(serializer.Deserialize(reader));
}
the value of result is this.
<BGBAResultadoOperacion><Severidad>OK</Severidad></BGBAResultadoOperacion><permiteOperar>true</permiteOperar><Lista><Codigo>ODM-006</Codigo><Descripcion>Aviso</Descripcion><DescripcionTecnica>xxxx</DescripcionTecnica></Lista>
What I need is to get the value of BGBAResultadoOperacion
when i set
using (StringReader reader = new StringReader(result))
{
result = (BGBAResultadoOperacion)(serializer.Deserialize(reader));
}
result get XML error...
There are multiple root elements. Line 1, position 76.
XML node out_policySystem has three root elements inside it. I need to parse only BGBAResultadoOperacion
How can I get it?
Thanks
That's because of this line:
elemlist[0].InnerXml
Which returns an XML Fragment, not an XML Document.
<BGBAResultadoOperacion>
<Severidad>OK</Severidad>
</BGBAResultadoOperacion>
<permiteOperar>true</permiteOperar>
<Lista xmlns:ns0=\"http://CalypsoPolicySystem_lib/service\">
<Codigo>ODM-006</Codigo>
<Descripcion>Aviso</Descripcion>
<DescripcionTecnica>XXXX</DescripcionTecnica>
</Lista>
So either use the .OuterXML, or use XElement.CreateReader() as described in the answer here: Serialize an object to XElement and Deserialize it in memory
When I'm deserializing a xml string, I need to save a XElement outerXml on a string property called prop2.
My XML:
<MyObj>
<prop1>something</prop1>
<prop2>
<RSAKeyValue>
<Modulus>...</Modulus>
<Exponent>...</Exponent>
</RSAKeyValue>
</prop2>
<prop3></prop3>
</MyObj>
My object:
public class MyObj
{
[XmlElement("prop1")]
public string prop1 { get; set; }
[XmlText]
public string prop2 { get; set; }
[XmlElement(ElementName = "prop3", IsNullable = true)]
public string prop3 { get; set; }
}
I'm deserializing using XmlSerializer, like this:
var serializer = new XmlSerializer(typeof(T));
return (T)serializer.Deserialize(new StringReader(myXmlString));
I tried to use [XmlText] to save XML text in prop2 But I'm only getting null.
What I need to do to save <RSAKeyValue><Modulus>...</Modulus><Exponent>...</Exponent></RSAKeyValue> like text in prop2?
XmlText will give value as XML encoded as text (">prop2<...") see XmlTextAttribute
By default, the XmlSerializer serializes a class member as an XML element. However, if you apply the XmlTextAttribute to a member, the XmlSerializer translates its value into XML text. This means that the value is encoded into the content of an XML element.
One possible solution - use XmlNode as type of the property:
public class MyObj
{
[XmlElement("prop1")]
public string prop1 { get; set; }
public XmlNode prop2 { get; set; }
[XmlElement(ElementName = "prop3", IsNullable = true)]
public string prop3 { get; set; }
}
var r = (MyObj)serializer.Deserialize(new StringReader(myXmlString));
Console.WriteLine(r.prop2.OuterXml);
Alternatively you may make whole object implement custom Xml serialization or have custom type that matches XML (to read normally) and have additional property to represent that object as XML string.
I need to serialize my C# class to XML looking something like so:
<request>
<session>12345</session>
<page>1</page>
<elements_per_page>999</elements_per_page>
<location>
<zone>aaaa</zone>
<region>bbbb</region>
<coordinates>
<lat>38.680632</lat>
<lon>-96.5001</lon>
</coordinates>
</location>
</request>
What I don't want is 3 classes (request, location, coordinates), I just want 1 class with all changable attributes as root of that class and then added some serialization tags that would create that nested XML, is that at all possible?
Let's start with the bare class:
[XmlRoot]
class request
{
[XmlElement]
public int session { get; set; }
[XmlElement]
public int page { get; set; }
[XmlElement]
public int elements_per_page { get; set; }
[?]
public string zone { get; set; }
[?]
public string region { get; set; }
[?]
public decimal lat { get; set; }
[?]
public decimal lon { get; set; }
}
How do I map them so the XML like I described is created? Thanks for your help good people :)
"is that at all possible?"
No. What's the problem of having 3 classes? How would you want to make a XML-to-static-code linking at all in some other way?
Moreover, if you just want to dirtly spit out some XML, you could use, for example, System.Xml.XmlDocument and build an xml from scratch which you could serialize with System.Xml.Serialization.XmlSerializer. Like this:
public string SerializeRequest(Request request)
{
XmlDocument document = new XmlDocument();
XmlElement requestElement = document.CreateElement("request");
XmlElement sessionElement = document.CreateElement("session");
sessionElement.InnerText = request.session.ToString(CultureInfo.InvariantCulture);
XmlElement pageElement = document.CreateElement("page");
pageElement.InnerText = request.page.ToString(CultureInfo.InvariantCulture);
XmlElement elementsPerPageElement = document.CreateElement("elements_per_page");
elementsPerPageElement.InnerText = request.elements_per_page.ToString(CultureInfo.InvariantCulture);
XmlElement zoneElement = document.CreateElement("zone");
zoneElement.InnerText = request.zone;
XmlElement regionElement = document.CreateElement("region");
regionElement.InnerText = request.region;
XmlElement latElement = document.CreateElement("lat");
latElement.InnerText = request.lat.ToString(CultureInfo.InvariantCulture);
XmlElement lonElement = document.CreateElement("lon");
lonElement.InnerText = request.lon.ToString(CultureInfo.InvariantCulture);
XmlElement coordinatesElement = document.CreateElement("coordinate");
coordinatesElement.AppendChild(latElement);
coordinatesElement.AppendChild(lonElement);
XmlElement locationElement = document.CreateElement("location");
locationElement.AppendChild(zoneElement);
locationElement.AppendChild(regionElement);
locationElement.AppendChild(coordinatesElement);
requestElement.AppendChild(sessionElement);
requestElement.AppendChild(pageElement);
requestElement.AppendChild(elementsPerPageElement);
requestElement.AppendChild(locationElement);
document.AppendChild(requestElement);
string serializedObj = document.OuterXml;
return serializedObj;
}