I want add a namespace in my xml root. Below is the result I want:
<ReconciliationRequest xmlns="http://schemas.xxx.co.xxx/test/crm">
<Patient>
<NHSNumber>1234567890</NHSNumber>
<PDSChangeSerialNumber>1234</PDSChangeSerialNumber>
</Patient>
<!-- ... -->
</ReconciliationRequest>
But I'm getting below result
<ReconciliationRequest>
<Patient>
<NHSNumber>1234567890</NHSNumber>
<PDSChangeSerialNumber>1234</PDSChangeSerialNumber>
</Patient>
<!-- ... -->
</ReconciliationRequest>
Below is the code I'm using to add the namespace:
TextWriter writer = new StreamWriter("D:\\ReconcillationRequest.xml");
XmlSerializerNamespaces nameSpace = new XmlSerializerNamespaces();
nameSpace.Add(string.Empty, "http://schemas.XXXX.co.XX/Test/crm");
serializer.Serialize(writer, obj, nameSpace);
writer.Close();
I'm unable to add the namespace. Please guide me on this.
Related
I am a new user on this forum and I'm not a highly experienced developer/programmer. Before asking this question, I searched and looked through Stack Overflow and some Microsoft suggested links, but I didn't find what I was looking for.
I've got the following XML file:
<?xml version="1.0" standalone="no" ?>
<WndPos name="FrontEnd.Login" l="703" r="1264" t="323" b="909" />
<LayerManager />
<ViewLayers name="RoofLayout" roof="1" nlwalls="1">
<Layer level="-1" module="1" name="Walls" locked="0" visible="1" />
</ViewLayers>
<DirProfiles>
<ProfileInfo ProfileName="ControlCQFT" JobPath="C:\Jobs" DatabasePath="D:\Database\ControlCQFT" />
</DirProfiles>
<DirHistory>
<ProfileInfo Use="Job" Path="C:\Jobs" />
</DirHistory>
I need to replace the entire <DirProfiles> node. The incoming node can be empty, which looks like <DirProfiles />. The new node that I want to insert is in the format:
<DirProfiles>
<ProfileInfo ProfileName="Control1" JobPath="D:\Client1\JobsA" DatabasePath="D:\Database\Control1" />
. . . . .
</DirProfiles>
I tried to handle the problem as a simple string replacement, but I didn't get the result that I needed.
Edit:
My apology, I didn't realized that my xml file is fragment xml document and not full XML as per spec.
Given your input file is a malformed XML file that doesn't contain a root node, you can get around this with a bit of string manipulation.
Here's the file you say you have:
<?xml version="1.0" standalone="no" ?>
<WndPos name="FrontEnd.Login" l="703" r="1264" t="323" b="909" />
<LayerManager />
<ViewLayers name="RoofLayout" roof="1" nlwalls="1">
<Layer level="-1" module="1" name="Walls" locked="0" visible="1" />
</ViewLayers>
<DirProfiles>
<ProfileInfo ProfileName="ControlCQFT" JobPath="C:\Jobs" DatabasePath="D:\Database\ControlCQFT" />
</DirProfiles>
<DirHistory>
<ProfileInfo Use="Job" Path="C:\Jobs" />
</DirHistory>
Here's how to work with it:
var sourceFileName = #"C:\{path}\xml_fragments.txt";
var text = $"<root>{String.Join(Environment.NewLine, File.ReadLines(sourceFileName).Skip(1))}</root>";
var doc = XDocument.Parse(text);
doc.Root.Element("DirProfiles").Elements().Remove();
doc.Root.Element("DirProfiles").Add(
new XElement(
"ProfileInfo",
new XAttribute("ProfileName", "Control1"),
new XAttribute("JobPath", #"D:\Client1\JobsA"),
new XAttribute("DatabasePath", #"D:\Database\Control1")));
That gives me:
<root>
<WndPos name="FrontEnd.Login" l="703" r="1264" t="323" b="909" />
<LayerManager />
<ViewLayers name="RoofLayout" roof="1" nlwalls="1">
<Layer level="-1" module="1" name="Walls" locked="0" visible="1" />
</ViewLayers>
<DirProfiles>
<ProfileInfo ProfileName="Control1" JobPath="D:\Client1\JobsA" DatabasePath="D:\Database\Control1" />
</DirProfiles>
<DirHistory>
<ProfileInfo Use="Job" Path="C:\Jobs" />
</DirHistory>
</root>
See following :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.IO;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
string xml = File.ReadAllText(FILENAME);
XElement doc = new XElement("Root");
doc.Add(XElement.Parse(xml));
XElement dirProfiles = doc.Descendants("DirProfiles").FirstOrDefault();
XElement profileInfo = dirProfiles.Element("ProfileInfo");
profileInfo.SetAttributeValue("ProfileName", "Control1");
profileInfo.SetAttributeValue("JobPath", #"D:\Client1\JobsA");
profileInfo.SetAttributeValue("DatabasePath", #"D:\Database\Control1");
}
}
}
You can parse the XML data to a C# class model, and after that could do the data changes as per requirement. After changes, you can again parse the model object to XML and rewrite the XML string on the same file.
Refer this link for generate a class structure by available XML: https://www.c-sharpcorner.com/blogs/convert-xml-json-file-to-c-sharp-class
And Use this code to Convert Xml to a C# class object
public static T ConvertXmlToObject<T>(String xml)
{
T result = default(T);
try
{
using (TextReader reader = new StringReader(xml))
{
try
{
result =
(T)new XmlSerializer(typeof(T)).Deserialize(reader);
}
catch (InvalidOperationException)
{
// Throw message for invalid XML
}
}
}
catch (Exception ex)
{
}
return result;
}
Call the function like :
var entity = ConvertXmlToObject<ModelClass>(XMLString);
User this code to convert again Object to XML
public static string ConvertObjectToXML<T>(T ModelClass)
{
XmlSerializer xsObject = new XmlSerializer(typeof(T));
var inputObject = ModelClass;
var xmlString = "";
using (var sw = new StringWriter())
{
using (XmlWriter writer = XmlWriter.Create(sw))
{
xsObject.Serialize(writer, inputObject);
xmlString = sw.ToString();
}
}
return xmlString;
}
Call this function like :
string xmlString = ConvertObjectToXML<ModelClass>(ModelClassObject);
I have a XML structer like that
<?xml version="1.0" encoding="utf-8"?>
<Product>
<ProductName>da</ProductName>
<PluginPath></PluginPath>
<Instances></Instances>
</Product>
and i serialize my object to string.
<?xml version="1.0"?>
<Instance xmlns:xsi="http://bla bla" xmlns:xsd="bla bla" UniqueId="d4820029b7d7">
<InstanceName>Instance MyTestPluginForm</InstanceName>
<Description>Test Plugin IW</Description>
<AddedDate>2016-10-19T11:05:10.7443404+02:00</AddedDate>
<LogSettings>
<LoggingLevel>None</LoggingLevel>
<LogFilePath /><MaximumSize>100</MaximumSize
<ClearAfterDays>7</ClearAfterDays>
<IsSaveActiviesToEventLog>false</IsSaveActiviesToEventLog>
</LogSettings>
<ProductSpecific/>
</Instance>
So I want to append the second one in the Instances node in the first xml. But as you see both has xml definition on the top and after serializazion i got xmlns:xsi and xmlns:xsd attributes.
How to solve this problem?
PS: I do not want to create XML elements. Because my xml schema is dynamic. It has to be done with serialization. (I already checked this sample)
I solved the problem. using the code here
public static void CreateXmlFile(Instance instance, string filePath)
{
var xml = "<?xml version=\"1.0\" encoding=\"utf-8\"?><Product><ProductName>da</ProductName><PluginPath></PluginPath><Instances></Instances></Product>";
XmlDocument xmlDocument = new XmlDocument();
xmlDocument.LoadXml(xml);
xmlDocument.Save(filePath);
XmlNode xnode = xmlDocument.CreateNode(XmlNodeType.Element, "Instances", null);
XmlSerializer xSeriz = new XmlSerializer(typeof(Instance));
XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
ns.Add("", "");
XmlWriterSettings writtersetting = new XmlWriterSettings();
writtersetting.OmitXmlDeclaration = true;
StringWriter stringwriter = new StringWriter();
using (XmlWriter xmlwriter = System.Xml.XmlWriter.Create(stringwriter, writtersetting))
{
xSeriz.Serialize(xmlwriter, instance, ns);
}
xnode.InnerXml = stringwriter.ToString();
XmlNode bindxnode = xnode.SelectSingleNode("Instance");
xmlDocument.DocumentElement.SelectSingleNode("Instances").AppendChild(bindxnode);
xmlDocument.Save(filePath);
}
I need to creat an XML in this form:
<?xml version="1.0" encoding="UTF-8"?>
<CastleConfigTop xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="xsd/c5c.xsd" Format="1">
<ProjectInfo ProjectCode="1" ProjectIdentifier="C5_Valeo_SL">
<ProjectName>TheProjectName</ProjectName>
</ProjectInfo>
<Options />
<ConfigFile Name="C5_Valeo_SL">
<History>
</History>
<Includes>
</Includes>
<Options>
</Options>
<DataTypes>
<Options>
<options />
</Options>
<ArgTypes />
<Enums />
<Lookups />
<Doc />
</DataTypes>
<Interfaces />
<Modules>
</Modules>
<ExexutionUnits />
<Doc></Doc>
</ConfigFile>
</CastleConfigTop>
And im using this code, where the object ccTop contains all the necessary classes:
public void saveXmlPath()
{
//xmldoc.Save(this.OutputPath+"\\"+projectName+".C5C");
XmlSerializer serializer = new XmlSerializer(typeof(CastleConfigTop));
string outpath = this.OutputPath + "\\" + projectName + ".C5C";
using (TextWriter writer = new StreamWriter(#outpath))
{
serializer.Serialize(writer, ccTop);
}
}
But the output XMl has the encoding style "utf-8" (lower case) and a different namespace like this:
<?xml version="1.0" encoding="utf-8"?>
<CastleConfigTop xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<ProjectInfo ProjectCode="1" ProjectIdentifier="C5_Valeo_SL">
<ProjectName> ProjectName </ProjectName>
</ProjectInfo>
<Options />
<ConfigFile Name="C5_Valeo_SL">
<History>
</History>
<Includes>
</Includes>
<Options>
</Options>
<DataTypes>
<Options />
<ArgTypes />
<Enums />
<Lookups />
<Doc />
</DataTypes>
<Interfaces />
<Modules>
</Modules>
<Difs>
</Difs>
<ExexutionUnits />
<Doc>SAS Volvo SPA</Doc>
</ConfigFile>
</CastleConfigTop>
Any Idea about how to make them exactly similar?
You can post-process this using LINQ to XML to get what you want.
Create an XDocument and serialize your object to this:
var doc = new XDocument();
using (var writer = doc.CreateWriter())
{
serializer.Serialize(writer, ccTop);
}
Then modify the declaration and attributes:
XNamespace xsi = "http://www.w3.org/2001/XMLSchema-instance";
doc.Root.Attributes()
.Where(a => a.IsNamespaceDeclaration && a.Value == "http://www.w3.org/2001/XMLSchema")
.Remove();
doc.Root.Add(new XAttribute(xsi + "noNamespaceSchemaLocation", "xsd/c5c.xsd"));
doc.Root.Add(new XAttribute("Format", 1));
And then write to disc. Note you can use XmlWriterSettings to set various options for writing, such as indentation.
var settings = new XmlWriterSettings
{
Indent = true
};
using (var writer = XmlWriter.Create(FILENAME, settings))
{
doc.WriteTo(writer);
}
Or if you can just use Save (which gives you less options, but the defaults should be fine):
doc.Save(FILENAME);
I wouldn't expect the declaration to be an issue in lower case, but if it is you'll have to modify this using some other means - XmlWriter takes an Encoding and will convert this internally to the lowercase form, so changing this in the XDocument won't help.
TextWriter writer = new StreamWriter(outpath , true, Encoding.ASCII);
You can have a try with these code
Try this
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
using System.IO;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
saveXmlPath();
}
const string FILENAME = #"c:\temp\test.xml";
public static void saveXmlPath()
{
CastleConfigTop ccTop = new CastleConfigTop();
XmlSerializer serializer = new XmlSerializer(typeof(CastleConfigTop));
XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
ns.Add("xsi","xsd/c5c.xsd");
ns.Add("", "http://www.w3.org/2001/XMLSchema-instance");
using (TextWriter writer = new StreamWriter(FILENAME))
{
serializer.Serialize(writer, ccTop, ns);
}
}
}
[XmlRoot(ElementName = "CastleConfigTop", Namespace = "xsi")]
public class CastleConfigTop
{
}
}
I have two classes which need to be in same xml file. The way the classes are done mean I'm having to serialize separately. Which I have managed to do. The first I do using TextWriter.
TextWriter writer = new StreamWriter(filepath);
serializer.Serialize(writer, class, ns);
This works fine. Then I wanted to add another class to the file. So did same but added that I want to append not overwrite.
TextWriter writer = new StreamWriter(filepath, true);
This adds the new class to end but also adds another declaration so my XML file reads.
<?xml version="1.0" encoding"utf-8"?>
<dog>
...
</dog>
<?xml version="1.0" encoding"utf-8"?>
<cat>
...
</cat>
I've tried to use XmlWriter so I could use XmlWriterSettings then chose false for OmitXmlDeclaration but then it overrides the previous class I serialized.
Your XML needs a root element to be valid XML.
<?xml version="1.0" encoding"utf-8"?>
<animals>
<dog/>
<cat/>
<animals>
You could create a List<Animal> and serialize it. But if you do not have the same superclass, you can try to create a class like this:
[Serializable]
public class AnimalCollection : IXmlSerializable
{
public void WriteXml(XmlWriter writer)
{
// Repeat for the Cat
writer.WriteStartElement("Dog");
XmlSerializer serializer = new XmlSerializer(TypeOf(Dog));
using (StringWriter stringWriter = new StringWriter())
{
serializer.Serialize(stringWriter, _dog);
string value = stringWriter.ToString();
writer.WriteRaw(value);
}
writer.WriteEndElement();
}
}
in the ReadXml and WriteXml you could use the generic serializer to serialize those objects then use the XmlWriter to write a startElement. endElement and include the serialized animal.
What you want to do is not valid XML, as it can only contain a single root element.
You could create a class to contain dog and cat, and serialize that.
How can I insert the following stylesheet information into my existing xml file which is created using C#?
<?xml-stylesheet type="text/xsl" href="_fileName.xsl"?>
Or.... Can I add this line at the time of creation of the new XML file?
Edit:
I tried to achieve the above using XmlSerialier (hit and trial), something like this:
// assumes 'XML' file exists.
XmlDocument doc = new XmlDocument();
XElement dataElements = XElement.Load("_fileName.xml");
XmlSerializer xs = new XmlSerializer(typeof(Parents));
var ms = new MemoryStream();
xs.Serialize(ms, parents);
ms.Seek(0, SeekOrigin.Begin); // rewind stream to beginning
doc.Load(ms);
XmlProcessingInstruction pi;
string data = "type=\"text/xsl\" href=\"_fileName.xsl\"";
pi = doc.CreateProcessingInstruction("xml-stylesheet", data);
doc.InsertBefore(pi, doc.DocumentElement); // insert before root
doc.DocumentElement.Attributes.RemoveAll(); // remove namespaces
But the output xml is getting corrupted:
<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="_fileName.xsl"?>
<parents />
Whereas the desired output is something like:
<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="_fileName.xsl"?>
<parents>
<parent>
<Child1>
<child2>
</parent>
</parents>
Did this help to understand what's my problem???
You didn't answer the question.. "what lib do you use".
Although I advise:
XDocument
if you would use it you could do something like:
XDocument document = new XDocument(new XDeclaration("1.0", "utf-8", "yes"));
document.Add(new XProcessingInstruction(
"xml-stylesheet", "type=\"text/xsl\" href=\"_fileName.xsl\""));
//and then your actual document...
document.Add(
new XElement("parent",
new XElement("child1"),
new XElement("child2")
)
);
EDIT:
Ok So you could do it like:
XDocument document = XDocument.Load("file");
document.AddFirst(new XProcessingInstruction(
"xml-stylesheet", "type=\"text/xsl\" href=\"LogStyle.xsl\""));
Is this what you're looking for?