Change order of xmlnamespace - c#

I was working on Xml serialization. My class is
[XmlRoot("urlset", Namespace = "http://www.sitemaps.org/schemas/sitemap/0.9")]
[XmlInclude(typeof(Url))]
public class UrlSet
{
[XmlAttribute("schemaLocation", Namespace = XmlSchema.InstanceNamespace)]
public string xsiSchemaLocation = "http://www.sitemaps.org/schemas/sitemap/0.9" +
"http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd";
}
Tried adding
XmlSerializerNamespaces xmlNameSpace = new XmlSerializerNamespaces();
xmlNameSpace.Add("xsi", "http://www.w3.org/2001/XMLSchema-instance");
Output its giving to me is
<urlset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd">
I need to have
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd">
I also tried adding empty namespace, But that adds prefix q to every element in xml. I also want to know if that order really matters as I am going to submit generated sitemap to google
Any solutions?

Related

Xml Root.add value with Special Character( :)

I have an XML file
which is
<?xml version="1.0" encoding="utf-8"?>
<urlset >
</urlset>
I'm trying to add an XElement with special characters (:) code behind
string xmlpath = #"~/myxml.xml";
string path = Server.MapPath(xmlpath);
string title="SomeString"
XDocument doc = XDocument.Load(path);
XElement root = new XElement("url");
root.Add(new XElement("Video:title", "title"));//here is the problem i have Special char (:) which not allowed
doc.Element("urlset").Add(root);
also i can't use &qoute; becuse it's contniue special char & Please i need help if any one can help i would be thankful thanks a lot for your time guys and thank a lot for giving time to read my queation
I'm trying to add an XElement with special characters (:) code behind
Try using a XmlDocument which will allow creating an XmlElement with specified name and namespace.
string xmlpath = #"~/myxml.xml";
string path = Server.MapPath(xmlpath);
XmlDocument doc = new XmlDocument();
doc.Load(path);
var mainRoot = doc.DocumentElement; //urlset element
var urlRoot = doc.CreateElement("url"); //create url element
urlRoot.AppendChild(doc.CreateElement("Video:title","title")); //add element to the url element
mainRoot.AppendChild(urlRoot); // add this new element to the main root of urlset
Example Output:
<?xml version="1.0" encoding="utf-8"?>
<urlset>
<url>
<Video:title xmlns:Video="title" />
</url>
</urlset>
Or if you just want a Video node with namespace of title...
urlRoot.AppendChild(doc.CreateElement("Video","title"));
The output of this above:
<?xml version="1.0" encoding="utf-8"?>
<urlset>
<url>
<Video xmlns="title"/>
</url>
</urlset>
Please let me know if this isn't your expected output.

Can you Serialize inside a set of Attributes by Set of Attributes?

I want a serialize a set of attributes all together to an XML file in a loop that runs. This loop runs within a set of folders . According to my Current implementation It only shows the last set of Attributes.
Here is my Current code ,
Student obj = JsonConvert.DeserializeObject < StudentModel (File.ReadAllText(file));
string Name = studentModel.name;
string number = studentModel.number;
string testPath = rootDirectory;
XmlSerializer serializer = new XmlSerializer(typeof(StudentModel));
System.IO.StreamWriter writer = new System.IO.StreamWriter(testPath + "\\Test.xml");
serializer.Serialize(writer, studentModel);
writer.Close();
My Current output is
<?xml version="1.0" encoding="utf-8"?>
<StudentModel xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<name>Max</name>
<number>1</number>
</StudentModel>
Required output is
<?xml version="1.0" encoding="utf-8"?>
<StudentModel xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<name>Max</name>
<number>1</number>
</StudentModel>
<StudentModel xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<name>Amy</name>
<number>2</number>
</StudentModel>
<StudentModel xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<name>Jack</name>
<number>3</number>
</StudentModel>
It seems to me, that what you want to do is serialize a list (or array) of StudentModel to an xml. Currently you are only serializing one instance of StudentModel and overwrite the resulting xml each iteration of the loop, leaving you with the last item. What you can do, is to create a class with a List() of StudentModel as Property and serialize that class instance, not needing a loop anymore.
The List property in your new class would then look something like this:
[XmlArray("StudentModels"), XmlArrayItem(typeof(StudentModel), ElementName = "StudentModel")]
public List<StudentModel> StudentModelList{ get; set; }

How do I get an attribute with namespace?

<?xml version="1.0" encoding="UTF-8"?>
<Root xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Element xsi:Attribute="Test"></Element>
</Root>
I'm trying to read the "xsi:Attribute" attribute; the code is like this:
var doc = XDocument.Load(new StringReader(xmlText));
var node = doc.Root.Descendants().First();
XNamespace myNamespace = "xsi";
var attribute = node.Attributes(myNamespace + "Attribute").First();
It throws a "Sequence contains no elements" exception in the last line. What am I doing wrong?
You need to use the actual namespace, not "xsi", which is just a local lookup within the XML file itself for the real namespace:
XNamespace myNamespace = "http://www.w3.org/2001/XMLSchema-instance";
Try this (I believe its more generic):
XNamespace myNamespace = doc.Root.GetNamespaceOfPrefix("xsi");

Add namespaces to serialized xml

I've got a pretty nasty problem with xml serialization - I need to add some special information to the resulting xml-file:
Currently, it looks like
<?xml version="1.0" encoding="iso-8859-1"?>
<ORDER_LIST>
<ORDER version="1.0" xmlns="http://www.opentrans.org/XMLSchema/1.0">... shortened ...</ORDER>
<ORDER version="1.0" xmlns="http://www.opentrans.org/XMLSchema/1.0">... shortened ...</ORDER>
<ORDER version="1.0" xmlns="http://www.opentrans.org/XMLSchema/1.0">... shortened ...</ORDER>
</ORDER_LIST>
but it should look like
<?xml version="1.0" encoding="iso-8859-1"?>
<ORDER_LIST>
<ORDER xmlns="http://www.opentrans.org/XMLSchema/1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opentrans.org/XMLSchema/1.0 openTRANS_ORDER_1_0_all_in_one.xsd" version="1.0" type="standard">... shortened ...</ORDER>
<ORDER xmlns="http://www.opentrans.org/XMLSchema/1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opentrans.org/XMLSchema/1.0 openTRANS_ORDER_1_0_all_in_one.xsd" version="1.0" type="standard">... shortened ...</ORDER>
<ORDER xmlns="http://www.opentrans.org/XMLSchema/1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opentrans.org/XMLSchema/1.0 openTRANS_ORDER_1_0_all_in_one.xsd" version="1.0" type="standard">... shortened ...</ORDER>
</ORDER_LIST>
The additional namespace (xmlns:xsi) and the xsi:schemaLocation / type attributes should be added to the result.
Actually my code is:
[XmlTypeAttribute(Namespace="http://www.opentrans.org/XMLSchema/1.0")]
public class OrderContainer
{
[XmlElementAttribute("ORDER")]
public List<ORDER> orderList;
}
---- snip ----
string xmlString;
XmlWriterSettings settings = new XmlWriterSettings()
{
Encoding = Encoding.GetEncoding("ISO-8859-1"),
Indent = true,
IndentChars = "\t",
NewLineChars = Environment.NewLine,
ConformanceLevel = ConformanceLevel.Document,
};
XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
ns.Add("", "");
var testOrder = new ORDER();
var orderContainer = new OrderContainer();
orderContainer.orderList = new List<ORDER>();
orderContainer.orderList.Add(testOrder);
XmlSerializer serializer = new XmlSerializer(typeof(List<ORDER>), new XmlRootAttribute("ORDER_LIST"));
using (MemoryStream ms = new MemoryStream())
{
using (XmlWriter writer = XmlTextWriter.Create(ms, settings))
serializer.Serialize(writer, orderList, ns);
xmlString = Encoding.ASCII.GetString(ms.ToArray());
}
Console.WriteLine(xmlString);
It works really fine - except for the namespaces and attributes on the ORDER elements.
Background-information: The ORDER class is created from the openTrans-definition (opentrans_order_1_0_all_in_one.xsd).
It's been translated into C# classes using Xsd2Code (Xsd2Code).
Because of the automatic generation, adorning the class with attributes is not easily possible - I guess?
Thanks for any hint!
(Edited some information)
I know its a little late to reply to this question, but nonetheless I am answering in case someone in need stumbles upon this question.
I order to add namespaces you need to use this class: System.Xml.Serialization. XmlSerializerNamespaces, which I see in the problem code that it has been defined.
Following is the syntax that I have used to add namespaces while dealing with the xCBL Xml Schema:
[XmlNamespaceDeclarations]
public XmlSerializerNamespaces xmlns; //Defined as the Field of the class you want to serialize
//Defined in the Constructor
xmlns = new XmlSerializerNamespaces();
xmlns.Add("core", "rrn:org.xcbl:schemas/xcbl/v4_0/core/core.xsd");
This will add the namespace in the generated Xml like this:
xmlns:core="rrn:org.xcbl:schemas/xcbl/v4_0/core/core.xsd"
What it should look like is:
<?xml version="1.0" encoding="iso-8859-1"?>
<ORDER_LIST xmlns:trans="http://www.opentrans.org/XMLSchema/1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opentrans.org/XMLSchema/1.0 http://www.opentrans.org/XMLSchema/1.0 openTRANS_ORDER_1_0_all_in_one.xsd" version="1.0" >
<trans:ORDER type="standard" >... shortened ...</ORDER>
<trans:ORDER type="standard" >... shortened ...</ORDER>
<trans:ORDER type="standard" >... shortened ...</ORDER>
</ORDER_LIST>
I'm not familar with xsd2code, but if you were hand coding, you need to put attributes.
[System.Xml.Serialization.XmlTypeAttribute(Namespace="http://www.opentrans.org/XMLSchema/1.0")]
[System.Xml.Serialization.XmlElementAttribute("Order")]
public class Order() {
String Type
}
[System.Xml.Serialization.XmlTypeAttribute(Namespace="http://www.opentrans.org/XMLSchema/1.0")]
[System.Xml.Serialization.XmlRootAttribute("OrderList", Namespace="http://www.opentrans.org/XMLSchema/1.0", IsNullable=false)]
public class OrderList() {
List<Orders>
}
try this. it's a libary to create or read opentrans documents!
http://opentrans.wordpress.com/

How to correctly parse an XML document with arbitrary namespaces

I am trying to parse somewhat standard XML documents that use a schema called MARCXML from various sources.
Here are the first few lines of an example XML file that needs to be handled...
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<marc:collection xmlns:marc="http://www.loc.gov/MARC21/slim" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.loc.gov/MARC21/slim http://www.loc.gov/standards/marcxml/schema/MARC21slim.xsd">
<marc:record>
<marc:leader>00925njm 22002777a 4500</marc:leader>
and one without namespace prefixes...
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<collection xmlns="http://www.loc.gov/MARC21/slim">
<record>
<leader>01142cam 2200301 a 4500</leader>
Key point: in order to get the XPaths to resolve further along in the program I have to go through a regex routine to add the namespaces to the NameTable (which doesn't add them by default). This seems unnecessary to me.
Regex xmlNamespace = new Regex("xmlns:(?<PREFIX>[^=]+)=\"(?<URI>[^\"]+)\"", RegexOptions.Compiled);
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(xmlRecord);
XmlNamespaceManager nsMgr = new XmlNamespaceManager(xmlDoc.NameTable);
MatchCollection namespaces = xmlNamespace.Matches(xmlRecord);
foreach (Match n in namespaces)
{
nsMgr.AddNamespace(n.Groups["PREFIX"].ToString(), n.Groups["URI"].ToString());
}
The XPath call looks something like this...
XmlNode leaderNode = xmlDoc.SelectSingleNode(".//" + LeaderNode, nsMgr);
Where LeaderNode is a configurable value and would equal "marc:leader" in the first example and "leader" in the second example.
Is there a better, more efficient way to do this? Note: suggestions for solving this using LINQ are welcome, but I would mainly like to know how to solve this using XmlDocument.
EDIT: I took GrayWizardx's advice and now have the following code...
if (LeaderNode.Contains(":"))
{
string prefix = LeaderNode.Substring(0, LeaderNode.IndexOf(':'));
XmlNode root = xmlDoc.FirstChild;
string nameSpace = root.GetNamespaceOfPrefix(prefix);
nsMgr.AddNamespace(prefix, nameSpace);
}
Now there's no more dependency on Regex!
If you know there is going to be a given element in the document (for instance the root element) you could try using GetNamespaceOfPrefix.

Categories

Resources