I am trying to use xmlwriter to customize my xml file. I have tried using a class to serialize to xml but it does not seem to work. My goal is to have multiple namespace definitions within the "AddO" element, with each element under the messages having a prefix.
Click event:
XmlWriterSettings objSetting = new XmlWriterSettings();
objSetting.Indent = true;
objSetting.NewLineOnAttributes = true;
System.Text.StringBuilder sb = new System.Text.StringBuilder();
using (XmlWriter objWriter = XmlWriter.Create(sb, objSetting))
{
//Request
objWriter.WriteStartDocument();
objWriter.WriteStartElement("Request");
objWriter.WriteStartElement("SName");
objWriter.WriteValue("AocD");
objWriter.WriteEndElement();
objWriter.WriteStartElement("Message");
//objWriter.WriteStartElement("pd", "AddO", "www.google.com");
objWriter.WriteStartElement("pd", "AddO", "www.google.com");
objWriter.WriteStartElement("aoc","CaseD");
objWriter.WriteStartElement("CaseA");
objWriter.WriteStartElement("DocE");
objWriter.WriteEndElement();
objWriter.WriteEndElement();
objWriter.WriteEndElement();
objWriter.WriteEndElement();//CaseD End
objWriter.WriteEndElement();//Message End
objWriter.WriteEndElement();//Request End
objWriter.WriteEndDocument();
File.WriteAllText(Server.MapPath("~/images/test.xml"), sb.ToString());
I get this XML Result:
<?xml version="1.0" encoding="utf-16"?>
<Request>
<SName>AocD</SName>
<Message>
<iepd:AddO xmlns:iepd="www.google.com">
<aoc xmlns="CaseD">
<CaseA>
<DocE>
</DocE>
</CaseA>
</aoc>
</iepd:AddO>
</Message>
</Request>
Trying to get:
<?xml version="1.0" encoding="utf-16"?>
<Request>
<SName>AocD</SName>
<Message>
<iepd:AddO xmlns:iepd="www.google.com" xmlns:a="www.goo.com" xmlns:b="www.gle.com" xmlns:d="www.le.com">
<a:CaseD">
<b:CaseA>
<d:DocE>
</d:DocE>
</b:CaseA>
</a:CaseD>
</iepd:AddO>
</Message>
</Request>
Related
I build an XML Document which needs to be validated against a xsd file. Thus I need a reference to the xsd file in the root element of the xml. So far I use this C# Code:
var ser = new XmlSerializer(typeof(myspecialtype));
XmlSerializerNamespaces MainNamespace = new XmlSerializerNamespaces();
MainNamespace.Add("xlink", "http://www.w3.org/1999/xlink");
MainNamespace.Add("xsi", "http://www.w3.org/2001/XMLSchema-instance");
using (XmlWriter w = XmlWriter.Create(#"C:\myxmlfile.xml"))
{
w.WriteProcessingInstruction("xml-stylesheet", "type=\"text/xsl\" href=\"utils/somexsl.xsl\"");
ser.Serialize(w, LeBigObject, HauptNs);
}
The resulting Xml begins like this:
<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="utils/somexsl.xsl"?>
<caddy-xml xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xlink="http://www.w3.org/1999/xlink" xmlVersion="03.07.00">
but I need this:
<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="utils/somexsl.xsl"?>
<caddy-xml xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xlink="http://www.w3.org/1999/xlink" xmlVersion="03.07.00" xsi:noNamespaceSchemaLocation="utils/theveryimportant.xsd">
I came across "CreateAttribute" here: Add Namespace to an xml root node c# but I can't put it together with the Serializer. Thank you!
I was pointed to the solution here:
https://social.msdn.microsoft.com/Forums/en-US/e43585c6-181b-4449-8806-b07f82681a2a/how-to-include-xsinonamespaceschemalocation-in-the-xml?forum=asmxandxml
I added this to my class:
[XmlAttribute("noNamespaceSchemaLocation", Namespace = XmlSchema.InstanceNamespace)]
public string attr = "utils/theveryimportant.xsd";
and it works.
I have an XML file with some data on it..for example
<?xml version="1.0" encoding="utf-8"?>
<CreateAndSendMessageRequest xmlns:xsi="http://www.w3.org/2001/XMLSchema-
instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="http://schemas.communisis.com/lv">
<CompositionRequest>
<Metadata xmlns="http://lv.com/gi/si/common/CommonTypes">
<PolicyReference>250028766505DN</PolicyReference>
<AccountReference>Test1234</AccountReference>
<QuoteReference>Test3214</QuoteReference>
<OutboundTransactionID>string</OutboundTransactionID>
</Metadata>
Now i want to replace POLICY REFERENCE value with some dummy data. I am able to do that but now i have to save it as a new file with a different file name..
How can i achieve that..
For reference i am giving my code.
XmlDocument doc = new XmlDocument();
doc.Load(filepath);
XmlNodeList node = doc.GetElementsByTagName("PolicyReference");
var item =node.Item(0);
string value = item.FirstChild.Value;
string nevalue = value.Replace(value, "Test123");
doc.DocumentElement.;
doc.Save(#"C:\Test\file.xml");
The xml wasn't valid.
Anyway, this is how to make it work:
Xml file:
<?xml version="1.0" encoding="UTF-8"?>
<CreateAndSendMessageRequest>
<CompositionRequest>
<Metadata xmlns="http://lv.com/gi/si/common/CommonTypes">
<PolicyReference>250028766505DN</PolicyReference>
<AccountReference>Test1234</AccountReference>
<QuoteReference>Test3214</QuoteReference>
<OutboundTransactionID>string</OutboundTransactionID>
</Metadata>
</CompositionRequest>
</CreateAndSendMessageRequest>
Code:
XmlDocument doc = new XmlDocument();
doc.Load("bho.xml");
XmlNodeList node = doc.GetElementsByTagName("PolicyReference");
node[0].InnerText = "Test123";
doc.Save("file.xml");
Result xml:
<?xml version="1.0" encoding="UTF-8"?>
<CreateAndSendMessageRequest>
<CompositionRequest>
<Metadata xmlns="http://lv.com/gi/si/common/CommonTypes">
<PolicyReference>Test123</PolicyReference>
<AccountReference>Test1234</AccountReference>
<QuoteReference>Test3214</QuoteReference>
<OutboundTransactionID>string</OutboundTransactionID>
</Metadata>
</CompositionRequest>
</CreateAndSendMessageRequest>
Hope it helps you ^^
I created a .NET class for XML serialization
[Serializable()]
[XmlRoot("documents")]
public class BdfXmlData
{
[XmlElement("document")]
public List<XmlElement> Documents { get; set; }
public BdfXmlData()
{
Documents = new List<XmlElement>();
}
}
When I try to serialize an object, I get with this tree:
<?xml version="1.0" encoding="utf-8"?>
<ArrayOfXmlElement xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<XmlElement>
<documents>
<document>
...
<document>
<documents>
</XmlElement>
</ArrayOfXmlElement>
How can I have the following three?
<?xml version="1.0" encoding="utf-8"?>
<documents>
<document>
...
<document>
<documents>
Thanks in advance.
The code to serialize my class is the following:
public static string GetSerializedObject<T>(T t)
{
using (MemoryStream stream = new MemoryStream())
{
XmlSerializer serializer = new XmlSerializer(typeof(T));
serializer.Serialize(stream, t);
stream.Position = 0;
using (StreamReader reader = new StreamReader(stream))
return reader.ReadToEnd();
}
}
I think you can at least simplify your xml-code:
<ArrayOfdocuments xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<documents>
<document>
...
<document>
<documents>
</ArrayOfdocuments>
The "XmlElement" element can be left out.
Surely you are serialising an array of BdfXmlData
in pseudo code
BdfXmlData[] dataInArray = new [] {new BdfXmlData()};
GetSerializedObject(dataInArray)
would produce what you have whereas,
in pseudo code..
BdfXmlData data = new BdfXmlData();
GetSerializedObject(data)
should give you what you want!
Exact, I serialise the Documents collection :
SerializationHelper.GetSerializedObject(xmlRootData.Documents);
In fact, I receive some XmlElement with this tree :
<document>
...
<document>
and I add these elements to my List "Documents".
xmlRootData.Documents.Add(xmlData);
When I serialise my final object (BdfXmlData), the xml contains 2 documents tags and 2 document tags
string xmlData = SerializationHelper.GetSerializedObject(xmlRootData);
<documents xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<document>
<documents>
<document>
</document>
<documents>
</document>
</documents>
I have successfully been able to transform a simple xml file with data to another xml file (excel template) using a xsl template, this is what my xsl file looks like:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" standalone="yes"/>
<xsl:template match="/">
<xsl:processing-instruction name="mso-application">
<xsl:text>progid="Excel.Sheet"</xsl:text>
</xsl:processing-instruction>
...(stuff here)...
</xsl:template>
</xsl:stylesheet>
The resulting xml file is written out correctly BUT with the exception of including
<?xml version="1.0"?>
at the top of the file. How can I get it to appear at the top?
Currently my resulting xml file starts with:
<?mso-application progid="Excel.Sheet"?>
...(rest of file)...
But what I need it to do is:
<?xml version="1.0"?>
<?mso-application progid="Excel.Sheet"?>
.(rest of file)...
I'm doing this transform through a windows form with the following code:
XPathDocument myXPathDoc = new XPathDocument(xmlfile);
XslCompiledTransform myXslTrans = new XslCompiledTransform();
myXslTrans.Load(xslfile);
XmlTextWriter myWriter = new XmlTextWriter(xmlexcelfile, null);
myWriter.Formatting = Formatting.Indented;
myWriter.Namespaces = true;
myXslTrans.Transform(myXPathDoc, null, myWriter);
myWriter.Close();
I've tried playing around with the xsl:output standalone="yes/no", as well as omit-xml-declaration="no". I've also tried (in the C#) code adding myWriter.WriteStartDocument(); before transforming but that was not allowed. I have tried searching online for this as well and keep coming back to the standalone="yes" but that isn't working. Is there something I am missing here? Oh and in case you are wondering why I need to have the
<?xml version="1.0"?>
at the top of the resulting file, it's because when opening the xml file with excel, excel doesn't recognize it correctly but if it is included then excel opens it correctly...
You can do this
<xsl:output method="xml" indent="yes" omit-xml-declaration="no" />
or something similar to this using XmlWriterSettings
Edit: Added more code. Previous was missing some parts
XmlWriterSettings writerSettings = null;
XsltArgumentList transformationArguments = null;
XslCompiledTransform transformer = null;
MemoryStream memoryStream = null;
XPathDocument xPathDocument = null;
StringBuilder sb = null;
XmlWriter writer = null;
XmlDocument resultXml = null;
try
{
writerSettings = new XmlWriterSettings();
writerSettings.OmitXmlDeclaration = false; // This does it
writerSettings.Indent = true;
transformationArguments = new XsltArgumentList();
transformer = new XslCompiledTransform();
memoryStream = new MemoryStream(System.Text.Encoding.Default.GetBytes(xml.OuterXml));
xPathDocument = new XPathDocument(new StreamReader(memoryStream));
sb = new StringBuilder();
// give the settings to the writer here
writer = XmlWriter.Create(sb, writerSettings);
// this is not mandatory, obviously, just passing parameters to my xslt file
foreach (KeyValuePair<string, object> parameter in parameters)
{
transformationArguments.AddParam(parameter.Key, string.Empty, parameter.Value);
}
using (Stream strm = Assembly.GetExecutingAssembly().GetManifestResourceStream("Lib.XSLTFile1.xslt"))
using (XmlReader reader = XmlReader.Create(strm))
{
transformer.Load(reader);
transformer.Transform(xPathDocument, transformationArguments, writer);
}
resultXml = new XmlDocument();
resultXml.LoadXml(sb.ToString());
// for testing only
File.AppendAllText(#"Your path goes here\result.xml", resultXml.OuterXml);
}
catch (Exception)
{
throw;
}
This is how I do it, but this code is specifically written to create an instance of a XmlDocument. I'm sure you can adapt to your needs.
I'm using this:
public void WriteSettings(string key, string value)
{
XmlWriterSettings xmlSettings = new XmlWriterSettings();
xmlSettings.Indent = true;
xmlSettings.NewLineOnAttributes = true;
XmlWriter writer = XmlWriter.Create(TMP_FULLPATH, xmlSettings);
writer.WriteStartElement("settings");
writer.WriteAttributeString(key, value);
writer.WriteEndAttribute();
writer.WriteEndDocument();
writer.Flush();
writer.Close();
}
But any modification replaces all attributes with only the last remaining attribute that I am trying to add. For example:
current XML:
<?xml version="1.0" encoding="utf-8"?>
<settings TitleFormat="name:%name% date:%date%" />
when I do:
WriteSettings("foo", "baa");
the XML is:
<?xml version="1.0" encoding="utf-8"?>
<settings foo="baa" />
instead of:
<?xml version="1.0" encoding="utf-8"?>
<settings TitleFormat="name:%name% date:%date%" foo="baa" />
How can I fix that?
You are writing a new file, with no consideration at all of the old. To update a document, you must load it into a DOM, edit the DOM, and save the DOM:
var doc = new XmlDocument();
doc.Load(path);
doc.DocumentElement.SetAttribute(key, value);
doc.Save(path);
you are creating new file each time you call XmlWriter.Create(), do something like this.