I'm trying to get an XML file generated using a namespace as such:
<namespace:Example1>
<namespace:Part1>Value1</namespace:Part1>
</namespace:Example1>
I've tried using
[XmlAttribute(Namespace = "namespace")]
public string Namespace { get; set; }
but I'm clearly missing something. The structure I've used is
[XmlRoot("Example1")]
public class Blah
{
[XmlAttribute(Namespace = "namespace")]
public string Namespace { get; set; }
but all I get is
<Example1>
<Part1>Value1</Part1>
</Example1>
Any help would be greatly appreciated.
Edit:
[XmlRoot(ElementName="Chart2", Namespace="vc")]
doesn't work.
You can use the XmlSerializerNamespaces class to add the prefix for a given namespace in the xml.
I hope the below code will he you better.
[XmlRoot(ElementName = "Example1")]
public class Blah
{
public string Part1 { get; set; }
}
Blah bl = new Blah();
bl.Part1 = "MyPart1";
// Serialization
/* Create an XmlSerializerNamespaces object and add two prefix-namespace pairs. */
XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
ns.Add("namespace", "test");
XmlSerializer s = new XmlSerializer(typeof(Blah),"test");
TextWriter w = new StreamWriter(#"c:\list.xml");
s.Serialize(w, bl,ns);
w.Close();
/* Output */
<?xml version="1.0" encoding="utf-8"?>
<namespace:Example1 xmlns:namespace="test">
<namespace:Part1>MyPart1</namespace:Part1>
</namespace:Example1>
Can you try this on your Model.cs:
Copy the whole XML, then on the Model.cs:
Edit > Paste Special > Paste XML as Classes.
Might help you. ;)
Related
I have an xml beginning like above
<Invoice
xsi:schemaLocation="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2../xsdrt/maindoc/UBL-Invoice-2.1.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xades="http://uri.etsi.org/01903/v1.3.2#"
xmlns:ext="urn:oasis:names:specification:ubl:schema:xsd:CommonExtensionComponents-2"
xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2"
xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2"
xmlns="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2">
<cbc:UBLVersionID>2.1</cbc:UBLVersionID>
<cbc:CustomizationID>TR1.2</cbc:CustomizationID>
<cbc:ProfileID>TEMELFATURA</cbc:ProfileID>
<cbc:ID>ALP2018000007216</cbc:ID>
<!-- ... -->
and I try to parse the xml with method like that
public static T FromXml<T>(string xmlString)
{
StringReader xmlReader = new StringReader(xmlString);
XmlSerializer deserializer = new XmlSerializer(typeof(T));
return (T)deserializer.Deserialize(xmlReader);
}
and my xml model is like above
[Serializable]
[XmlRoot(
Namespace = "urn:oasis:names:specification:ubl:schema:xsd:Invoice-2",
ElementName = "Invoice",
DataType = "string",
IsNullable = true)]
public class Invoice
{
public string CustomizationID { get; set; }
// ...
}
However, I cannot parse the xml document, all values come null. I think that it is because of multiple xmlns attribute in Invoice tag. I couldnt solve the problem.
The default namespace of the document is urn:oasis:names:specification:ubl:schema:xsd:Invoice-2 which you have correctly put in the XmlRoot, but the child elements such as UBLVersionID are prefixed with cbc, which is a different namespace. You have to put that namespace against the property to let the serializer know that's what it is.
For example:
[Serializable]
[XmlRoot(
Namespace = "urn:oasis:names:specification:ubl:schema:xsd:Invoice-2",
ElementName = "Invoice",
DataType = "string",
IsNullable = true)]
public class Invoice
{
[XmlElement(Namespace = "urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2")]
public string CustomizationID { get; set; }
// ...
}
In Visual Studio, you can use Edit > Paste Special > Paste Xml As Classes to see how to decorate a class to match your XML if you're in doubt.
I am receiving xml that contains embedded xhtml.
I would like to return the DocBody Element as a string that contains all of the xhtml, but do not know how since the xhtml is contained within the xml. I have not seen many examples of how to do this.
I am receiving this result via an API so the XML cannot be modified.
<Documents xmlns="http://mycompany.com/api/v2" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<Document>
<Content i:type="CreditAnalystNote">
<DocBody>
<xhtml>
<p>
Paragrah 1 html.
</p>
<p>
Paragrah 2 html.
</p>
<p>
Paragrah 3 html.
</p>
<p>
Paragrah 4 html.
</p>
</xhtml>
</DocBody>
</Content>
</Document>
</Documents>
The class I am using to deserialize the XML with is given as follows:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Xml.Serialization;
namespace Corporate
{
[Serializable]
[XmlRoot(ElementName = "Documents", Namespace = "http://cms.mycompany.com/api/v2")]
public class RPSShareclassDocuments
{
[XmlElement(ElementName = "Document")]
public List<ShareClassDocumentData> DocumentData { get; set; }
}
[Serializable]
public class ShareClassDocumentData
{
[XmlElement("Content")]
public DocumentShareClassData CreditNote { get; set; }
}
[XmlType("CreditAnalystNote")]
public class DocumentShareClassData
{
[XmlElement]
public string DocBody { get; set; }
}
}
I am attempting to deserialize the text using the following:
XDocument xDocResult = new XDocument();
xDocResult = ... (gets content into an XDocument)
IXmlUtils xmlUtility = new XmlUtils();
RPSShareclassDocuments document = xmlUtility.Deserialize<RPSShareclassDocuments>(xDocResult);
and the Deserialization method is:
public T Deserialize<T>(XDocument doc)
{
string szNamespace = doc.Root.Name.Namespace.NamespaceName;
XmlSerializer serializer = new XmlSerializer(typeof(T), szNamespace);
T result;
using (System.Xml.XmlReader reader = doc.CreateReader())
{
result = (T)serializer.Deserialize(reader);
}
return result;
}
EDIT 1
The only way that I could figure out how to extract the XHTML from the XML was to use the following code, though this is not what I was hoping for.
xDocResult = restClient.RestGET(szCurrentSecurityAPI);
XNamespace ns = xDocResult.Root.Name.Namespace.NamespaceName;
XElement xdb = xDocResult.Root.Element(ns + "Document").Element(ns + "Content").Element(ns + "DocBody").Element(ns + "xhtml");
If there is a better option such as extracting the information from the XDocument directly or XSLT, I would also be interested.
<?xml version="1.0" encoding="UTF-8"?>
<rs:model-request xsi:schemaLocation="http://www.ca.com/spectrum/restful/schema/request ../../../xsd/Request.xsd " xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:rs="http://www.ca.com/spectrum/restful/schema/request" throttlesize="100">
<rs:target-models>
I am having trouble understanding the C# XmlSerializer. I have successfully been able to serialize elements that do not have a prefix such as rs:* above. I also have no been able to find how to add the xsi:, xmlns:xsi and xmlns:rs (namespaces?).
Would someone be able to create a simple class to show how to generate the above XML?
Fields, properties, and objects can have a namespace associated with them for serialization purposes. You specify the namespaces using attributes such as [XmlRoot(...)], [XmlElement(...)], and [XmlAttribute(...)]:
[XmlRoot(ElementName = "MyRoot", Namespace = MyElement.ElementNamespace)]
public class MyElement
{
public const string ElementNamespace = "http://www.mynamespace.com";
public const string SchemaInstanceNamespace = "http://www.w3.org/2001/XMLSchema-instance";
[XmlAttribute("schemaLocation", Namespace = SchemaInstanceNamespace)]
public string SchemaLocation = "http://www.mynamespace.com/schema.xsd";
public string Content { get; set; }
}
Then you associate the desired namespace prefixes during serialization by using the XmlSerializerNamespaces object:
var obj = new MyElement() { Content = "testing" };
var namespaces = new XmlSerializerNamespaces();
namespaces.Add("xsi", MyElement.SchemaInstanceNamespace);
namespaces.Add("myns", MyElement.ElementNamespace);
var serializer = new XmlSerializer(typeof(MyElement));
using (var writer = File.CreateText("serialized.xml"))
{
serializer.Serialize(writer, obj, namespaces);
}
The final output file looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<myns:MyRoot xmlns:myns="http://www.mynamespace.com" xsi:schemaLocation="http://www.mynamespace.com/schema.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<myns:Content>testing</myns:Content>
</myns:MyRoot>
I am dealing with an API that occasionally changes the namespaces on the XML that I receive. The XML structure remains the same. I need to deserialize the XML into a strongly typed model.
How do I perform the deserialization regardless of what namespace is on the XML?
I was using a model like this:
[Serializable, XmlRoot(ElementName = "TestModel", Namespace = "http://schemas.datacontract.org/UnknownNamespace1")]
public class TestModel
{
public TestModel()
{
TestElements = new List<TestModelChildren>();
}
[XmlElement("TestModelChildren")]
public List<TestModelChildren> TestElements { get; set; }
}
I try to deserialize some XML into that model with code like this:
public TestModel DeserializeIt(XDocument xDoc)
{
TestModel result;
var serializer = new XmlSerializer(typeof(TestModel));
using(var sr = new StringReader(xDoc.ToString()))
{
result = (TestModel)serializer.Deserialize(sr);
}
return result;
}
My problem is that every so often, the namespace on the XML I am receiving changes. I might start getting XML like this:
<TestModel xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/UnknownNamespace2">
<TestModelChildren>
...
</TestModelChildren>
</TestModel>
I don't want to have to recompile my code every time this namespace change happens. How do I deal with it?
I was able to solve the problem by passing the namespace in to the XmlSerializer as a default namespace. I can pluck the namespace off of the XDocument to do this.
My new model would look like this without a namespace specified:
[Serializable, XmlRoot(ElementName = "TestModel")]
public class TestModel
{
public TestModel()
{
TestElements = new List<TestModelChildren>();
}
[XmlElement("TestModelChildren")]
public List<TestModelChildren> TestElements { get; set; }
}
My code to deserialize the XML would look like this:
public TestModel DeserializeIt(XDocument xDoc)
{
TestModel result;
var serializer = new XmlSerializer(typeof(TestModel), xDoc.Root.Name.Namespace.ToString());
using(var sr = new StringReader(xDoc.ToString()))
{
result = (TestModel)serializer.Deserialize(sr);
}
return result;
}
This has been working for me.
I have XML file like this:
<?xml version="1.0"?>
<catalog>
<book id="1" date="2012-02-01">
<title>XML Developer's Guide</title>
<price>44.95</price>
<description>
An in-depth look at creating applications
with XML.
</description>
</book>
<book id="2" date="2013-10-16">
<author>Mark Colsberg</author>
<title>Dolor sit amet</title>
<price>5.95</price>
<description>Lorem ipsum</description>
</book>
</catalog>
How to quick convert it to C# classes to use access data by LINQ?
Do I have to write the class manually for any XML file case?
What about JSON format?
Is the XSD the only solution?
You have two possibilities.
Method 1. XSD tool
Suppose that you have your XML file in this location C:\path\to\xml\file.xml
Open Developer Command Prompt
You can find it in Start Menu > Programs > Microsoft Visual Studio 2012 > Visual Studio Tools
Or if you have Windows 8 can just start typing Developer Command Prompt in Start screen
Change location to your XML file directory by typing cd /D "C:\path\to\xml"
Create XSD file from your xml file by typing xsd file.xml
Create C# classes by typing xsd /c file.xsd
And that's it! You have generated C# classes from xml file in C:\path\to\xml\file.cs
Method 2 - Paste special
Required Visual Studio 2012+
Copy content of your XML file to clipboard
Add to your solution new, empty class file (Shift+Alt+C)
Open that file and in menu click Edit > Paste special > Paste XML As Classes
And that's it!
Usage
Usage is very simple with this helper class:
using System;
using System.IO;
using System.Web.Script.Serialization; // Add reference: System.Web.Extensions
using System.Xml;
using System.Xml.Serialization;
namespace Helpers
{
internal static class ParseHelpers
{
private static JavaScriptSerializer json;
private static JavaScriptSerializer JSON { get { return json ?? (json = new JavaScriptSerializer()); } }
public static Stream ToStream(this string #this)
{
var stream = new MemoryStream();
var writer = new StreamWriter(stream);
writer.Write(#this);
writer.Flush();
stream.Position = 0;
return stream;
}
public static T ParseXML<T>(this string #this) where T : class
{
var reader = XmlReader.Create(#this.Trim().ToStream(), new XmlReaderSettings() { ConformanceLevel = ConformanceLevel.Document });
return new XmlSerializer(typeof(T)).Deserialize(reader) as T;
}
public static T ParseJSON<T>(this string #this) where T : class
{
return JSON.Deserialize<T>(#this.Trim());
}
}
}
All you have to do now, is:
public class JSONRoot
{
public catalog catalog { get; set; }
}
// ...
string xml = File.ReadAllText(#"C:\path\to\xml\file.xml");
var catalog1 = xml.ParseXML<catalog>();
string json = File.ReadAllText(#"C:\path\to\json\file.json");
var catalog2 = json.ParseJSON<JSONRoot>();
Here you have some Online XML <--> JSON Converters: Click
You can follow this simple step
1.Please Add using System.Xml as a reference;
2.Make a class named book in this way
public class book
{
public Nullable<System.DateTime> date{ get; set; }
public decimal price { get; set; }
public string title { get; set; }
public string description { get; set; }
}
try
{
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load("Write down full path");
XmlNodeList dataNodes = xmlDoc.SelectNodes("/catalog");
foreach (XmlNode node in dataNodes)
{
book objbook = new book();
objbook.date=Convert.ToDateTime(node.Attributes["date"].Value);
objbook.title=node.SelectSingleNode("title").InnerText;
objbook.description=node.SelectSingleNode("description").InnerText;
objbook.price=Convert.ToDecimal(node.SelectSingleNode("price").InnerText);
}
}
catch(Exception ex)
{
throw ex;
}
Use the XML Schema Definition Tool xsd.exe found in your framework tools to convert your schema into a serializable class or dataset.
xsd file.xsd {/classes | /dataset} [/element:element]
[/language:language] [/namespace:namespace]
[/outputdir:directory] [URI:uri]
And in example, whereas the C# class will be generated in the same directory as the xsd tool:
xsd /c YourFile.xsd
Use the super simple way using 'Paste XML As Classes' functionality in Visual studio menu.
1.copy the xml source in the clipboard, something like CTRL+A and CTRL+C
2.Go to 'Edit' Menu -> Paste Special -> Paste XML As Classes, to paste the generated classes based on the source xml"
Ref: More steps in detail at this link
Here is one another easy way to parse xml file using Cinchoo ETL, an open source library
Define POCO class as below
public class Book
{
[ChoXPath("#id")]
public int Id { get; set; }
[ChoXPath("#date")]
public DateTime Date { get; set; }
[ChoXPath("author")]
public string Author { get; set; }
[ChoXPath("title")]
public string Title { get; set; }
[ChoXPath("price")]
public double Price { get; set; }
[ChoXPath("description")]
public string Description { get; set; }
}
Use it to the parser as below
using (var r = new ChoXmlReader<Book>("*** Xml file path ***")
.WithXPath("//catalog/book", true)
)
{
foreach (var rec in r)
rec.Print();
}
Sample fiddle: https://dotnetfiddle.net/3UI82F