I'm trying to write an XML file for OpenClinica, a clinical trial platform who uses CDISC ODM XML representation.
My problem is when I try to write the very first element of the XML with an XmlWriter, I have this exception :
An exception of type 'System.Xml.XmlException' occurred in System.Xml.dll but
was not handled in user code
Additional information: The prefix '' cannot be redefined from '' to
'http://www.cdisc.org/ns/odm/v1.3' within the same start element tag.
Here's what I want in my file :
<ODM xmlns="http://www.cdisc.org/ns/odm/v1.3"
xmlns:OpenClinica="http://www.openclinica.org/ns/odm_ext_v130/v3.1"
xmlns:OpenClinicaRules="http://www.openclinica.org/ns/rules/v3.1"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
FileOID="testD20161121140900+0000"
Description="test"
CreationDateTime="2016-11-21T14:09:00+00:00"
FileType="Snapshot"
ODMVersion="1.3"
xsi:schemaLocation="http://www.cdisc.org/ns/odm/v1.3 OpenClinica-ODM1-3-0-OC2-0.xsd">
And here's my code :
StringWriter swriter = new StringWriter();
XmlWriter writer = XmlWriter.Create(swriter);
writer.WriteStartElement("ODM");
writer.WriteAttributeString("xmlns", "http://www.cdisc.org/ns/odm/v1.3");
writer.WriteAttributeString("xmlns", "OpenClinica", null, "http://www.openclinica.org/ns/odm_ext_v130/v3.1");
writer.WriteAttributeString("xmlns","OpenClinicaRules",null, "http://www.openclinica.org/ns/rules/v3.1");
writer.WriteEndElement();
writer.Close();
return swriter.ToString();
If I try to write only the "xmlns:OpenClinica" and the "xmlns:OpenClinicaRules" attributes, it's going well but the problem occurs when I try to write the xmlns attribute.
What could be the problem here ?
Try the following:
writer.WriteStartElement("","ODM","http://www.cdisc.org/ns/odm/v1.3");
Related
I have a c# application, where I'm doing a data compare of two xml files inside a method called RevisionTree. I return a list of elements(XElement) from this method. From the BuildXml method, call that method and save the list as tree. Next I create an xml root XElement. I then loop over each element from tree and add specified descendants (status, msg, date) to the root element, each one of these are XElement. So i should see an xml doument with root, then a list of repeating xml. However, when i try to save the to the writer i get the following error.
Error
Exception thrown: 'System.InvalidOperationException' in System.Private.Xml.dll
An unhandled exception of type 'System.InvalidOperationException' occurred in System.Private.Xml.dll
Token StartDocument in state Document would result in an invalid XML document.
Code
{
IEnumerable<XElement>
var tree = RevisionTree("C:\\Users\\Owner\\source\\repos\\SvnCore\\SvnCore\\old_logs.xml", "C:\\Users\\Owner\\source\\repos\\SvnCore\\SvnCore\\new_logs.xml");
using (XmlWriter writer = XmlWriter.Create("C:\\Users\\Owner\\source\\repos\\SvnCore\\SvnCore\\Temp.xml", xmlSettings))
{
writer.WriteStartDocument();
var root = new XElement("root");
foreach (var node in tree)
{
root.Add(new XElement("id", node.FirstAttribute));
root.Add(node.Descendants("status").FirstOrDefault());
root.Add(node.Descendants("msg").FirstOrDefault());
root.Add(node.Descendants("date").FirstOrDefault());
}
root.Save(writer);
writer.WriteEndElement();
writer.WriteEndDocument();
}
return true;
}
XElement.Save produces an entire document on its own -- you need XElement.WriteTo, which does not. So either (simplified):
var sb = new StringBuilder();
using (var sw = new StringWriter(sb))
using (XmlWriter writer = XmlWriter.Create(sw)) {
var root = new XElement("root");
root.Add(new XElement("id", "1"));
root.Save(writer); // no DocumentStart, no ElementStart
}
<?xml version="1.0" encoding="utf-16"?><root><id>1</id></root>
or (if you wanted to write multiple elements, or for some other reason want to control the document node yourself):
using (XmlWriter writer = XmlWriter.Create(sw)) {
writer.WriteStartDocument();
writer.WriteStartElement("root");
var notRoot = new XElement("notRoot");
notRoot.Add(new XElement("id", "1"));
notRoot.WriteTo(writer);
notRoot.WriteTo(writer);
}
<?xml version="1.0" encoding="utf-16"?><root><notRoot><id>1</id></notRoot><notRoot><id>1</id></notRoot></root>
Note that I'm omitting the End calls, since the XmlWriter will take care of that implicitly.
If you aren't doing anything interesting with the xmlSettings, the whole thing is even simpler since XElement.Save has an overload that accepts a file name directly, so you don't need an XmlWriter at all.
I have to generate specific XML data from code.
The XML needs to look like this
<this:declarationIdentifier xmlns:this="demo.org.uk/demo/DeclarationGbIdentifier"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="demo.org.uk/demo/DeclarationGbIdentifier DeclarationGbIdentifier.xsd"
xmlns:nsIdentity="demo.org.uk/demo/DeclarationGbIdentityType">
<this:declarationIdentity>
<nsIdentity:declarationUcr>Hello World</nsIdentity:declarationUcr>
</this:declarationIdentity>
</this:declarationIdentifier>
I have dabbled with XmlSerializer and XDocument but cant get the output to match this exactly
Please help.
I believe this will produce your desired output. There possibly is a simpler way this is just off the cuff to get you started. With the prefixes that you are requiring I would look up XmlDocument and adding namespaces to it to have a better understanding of what the code below is doing. Also what I would do is attempt to acquire the XSD schema file and use the XSD.exe to build a .cs file and then you can move forward with the XmlSerializer. If you move forward with the code below i highly suggest moving off your namespaceuri's into some soft of settings file so you can easily modify them in the event they change.
XmlDocument doc = new XmlDocument();
XmlElement root = doc.CreateElement("this", "declarationIdentifier", "demo.org.uk/demo/DeclarationGbIdentifier");
root.SetAttribute("xmlns:this", "demo.org.uk/demo/DeclarationGbIdentifier");
root.SetAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
//Just setting an Attribute of xsi:schemaLocation it would always drop the xsi prefix in the xml so this is different to accomodate that
XmlAttribute schemaAtt = doc.CreateAttribute("xsi", "schemaLocation", "http://www.w3.org/2001/XMLSchema-instance");
schemaAtt.Value = "demo.org.uk/demo/DeclarationGbIdentifier DeclarationGbIdentifier.xsd";
root.Attributes.Append(schemaAtt);
root.SetAttribute("xmlns:nsIdentity", "demo.org.uk/demo/DeclarationGbIdentityType");
doc.AppendChild(root);
XmlElement declarationIdentity = doc.CreateElement("this", "declarationIdentity", "demo.org.uk/demo/DeclarationGbIdentifier");
XmlElement declarationUcr = doc.CreateElement("nsIdentity","declarationUcr","demo.org.uk/demo/DeclarationGbIdentityType");
declarationUcr.InnerText = "Hello World";
declarationIdentity.AppendChild(declarationUcr);
doc.DocumentElement.AppendChild(declarationIdentity);
To output this as a string or dump it off to a file you can use the following operations, I output to a file as well as output to the console in my test app.
using (var stringWriter = new StringWriter())
using (StreamWriter writer = new StreamWriter(#"C:\<Path to File>\testing.xml"))
using (var xmlTextWriter = XmlWriter.Create(stringWriter))
{
doc.WriteTo(xmlTextWriter);
xmlTextWriter.Flush();
writer.Write(stringWriter.GetStringBuilder().ToString());
Console.WriteLine(stringWriter.GetStringBuilder().ToString());
}
I have an XML file that I deserialize, the funny part is the XML file is the was serialized
using the following code:
enter code here
var serializer = new XmlSerializer(typeof(CommonMessage));
var writer = new StreamWriter("OutPut.txt");
serializer.Serialize(writer, commonMessage);
writer.Close();
And i m trying to deserialized it again to check if the output match the input.
anyhow here is my code to deserialize:
var serializer = new XmlSerializer(typeof(CommonMessage));
var reader = new StringReader(InputFileName);
CommonMessage commonMessage = (CommonMessage)serializer.Deserialize(reader);
Replace StringReader with StreamReader and it will work fine. StringReader reads value from the string (which is file name in your case).
I just had the same error message but different error source. In case someone has the same problem like me. I chopped off the very first char of my xml string by splitting strings. And the xml string got corrupted:
"?xml version="1.0" encoding="utf-16"?> ..." // my error
"<?xml version="1.0" encoding="utf-16"?> ..." // correct
(1,1) means basically first char of the first line is incorrect and the string can't be deserialized.
include in your CommonMessage class the XmlRoot element tag with your xmlroot eg:[XmlRoot("UIIVerificationResponse")]
You should disable the order mark in the StreamWriter constructor like this:
UTF8Encoding(false)
Full sample:
using (MemoryStream stream = new MemoryStream())
using (StreamWriter writer = new StreamWriter(stream, new UTF8Encoding(false)))
{
xmlSerializer.Serialize(writer, objectToSerialize, ns);
return Encoding.UTF8.GetString(stream.ToArray());
}
I am serializing an object in my ASP.net MVC program to an xml string like this;
StringWriter sw = new StringWriter();
XmlSerializer s = new XmlSerializer(typeof(mytype));
s.Serialize(sw, myData);
Now this give me this as the first 2 lines;
<?xml version="1.0" encoding="utf-16"?>
<GetCustomerName xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
my question is,
How can I change the xmlns and the encoding type, when serializing?
Thanks
What I found that works was to add this line to my class,
[System.Xml.Serialization.XmlRootAttribute(Namespace = "http://myurl.com/api/v1.0", IsNullable = true)]
and add this to my code to add namespace when I call serialize
XmlSerializerNamespaces ns1 = new XmlSerializerNamespaces();
ns1.Add("", "http://myurl.com/api/v1.0");
xs.Serialize(xmlTextWriter, FormData, ns1);
as long as both namespaces match it works well.
The XmlSerializer type has a second parameter in its constructor which is the default xml namespace - the "xmlns:" namespace:
XmlSerializer s = new XmlSerializer(typeof(mytype), "http://yourdefault.com/");
To set the encoding, I'd suggest you use a XmlTextWriter instead of a straight StringWriter and create it something like this:
XmlWriterSettings settings = new XmlWriterSettings();
settings.Encoding = Encoding.UTF8;
XmlTextWriter xtw = XmlWriter.Create(filename, settings);
s.Serialize(xtw, myData);
In the XmlWriterSettings, you can define a plethora of options - including the encoding.
Take a look at the attributes that control XML serialization in .NET.
Specifically, the XmlTypeAttribute may be useful for you. If you're looking to change the default namespace for you XML file, there is a second parameter to the XmlSerializer constructor where you can define that.
I realize that SOAP webservices in .NET return XML representation of whatever object the web method returns, but if I want to return data formatting in XML what is the best object to store it in?
I am using the answer to this question to write my XML, here is the code:
XmlWriter writer = XmlWriter.Create(pathToOutput);
writer.WriteStartDocument();
writer.WriteStartElement("People");
writer.WriteStartElement("Person");
writer.WriteAttributeString("Name", "Nick");
writer.WriteEndElement();
writer.WriteStartElement("Person");
writer.WriteStartAttribute("Name");
writer.WriteValue("Nick");
writer.WriteEndAttribute();
writer.WriteEndElement();
writer.WriteEndElement();
writer.WriteEndDocument();
writer.Flush();
Now I can return this output as a String to my calling webmethod, but it shows up as <string> XML HERE </string>, is there anyway to just return the full xml?
Please in your answer, give an example of how to use said object with either XmlWriter or another internal object (if you consider XmlWriter to be a poor choice). The System.Xml package (namespace) has many objects, but I haven't been able to uncover decent documentation on how to use the objects together, or what to use for what situations.
This is how I ended up doing it;
StringBuilder sb = new StringBuilder();
XmlWriter writer = XmlWriter.Create(sb, settings);
writer.WriteStartDocument();
writer.WriteStartElement("People");
writer.WriteStartElement("Person");
writer.WriteAttributeString("Name", "Nick");
writer.WriteEndElement();
writer.WriteStartElement("Person");
writer.WriteStartAttribute("Name");
writer.WriteValue("Nick");
writer.WriteEndAttribute();
writer.WriteEndElement();
writer.WriteEndElement();
writer.WriteEndDocument();
writer.Flush();
XmlDocument xmlDocument = new XmlDocument();
xmlDocument.LoadXml(sb.ToString());
return xmlDocument;
May not be the best method, but it appears to be working. Let me know if you have a better method. Thanks.
Just return a XmlDocument. e.g.
[WebMethod]
public XmlDocument Quux()
{
}
XmlElement, not XmlDocument.
Return an XmlElement.
you can have a class that represent your XML and return that class or also return your xml inside an XMLNode