I have done this code so far works well, but the only issue is that the XML file gets deleted every time I use the method addUser, I want the code to continue writing under it
the code I wrote in c#:
public static void AddUser(PersonData pd)
{
XmlTextWriter xWriter = new XmlTextWriter("D:\\PersonData.Xml", Encoding.UTF8);
xWriter.Formatting = Formatting.Indented;
xWriter.WriteStartElement("User");
xWriter.WriteAttributeString("idNumber", pd.IdNumber1);
xWriter.WriteStartElement("Firstname");
xWriter.WriteString(pd.FirstName1);
xWriter.WriteEndElement();//<FirstName>
xWriter.WriteStartElement("LastName");
xWriter.WriteString(pd.LastName1);
xWriter.WriteEndElement();//<LastName>
xWriter.WriteStartElement("DateOfBirth");
xWriter.WriteString(pd.DateOfBirth1.ToString());
xWriter.WriteEndElement();//<DateOfBirth>
xWriter.WriteStartElement("Address");
xWriter.WriteString(pd.Address1);
xWriter.WriteEndElement();//<Address>
xWriter.WriteEndElement();//<user>
xWriter.Close();
}
the XML output:
<User idNumber="316447077">
<Firstname>majd</Firstname>
<LastName>sadi</LastName>
<DateOfBirth>29/03/1998 14:54:50</DateOfBirth>
<Address>hohos</Address>
</User>
the XML output that I want to do:
<User idNumber="316447077">
<Firstname>majd</Firstname>
<LastName>sadi</LastName>
<DateOfBirth>29/03/1998 14:54:50</DateOfBirth>
<Address>hohos</Address>
</User>
<User idNumber="316447077">
<Firstname>majd</Firstname>
<LastName>sadi</LastName>
<DateOfBirth>29/03/1998 14:54:50</DateOfBirth>
<Address>hohos</Address>
</User>
Assuming you have a root node to your XML (not valid XML without it), you could do this with XElement:
XElement xe;
if (File.Exists("D:\\PersonData.Xml"))
xe = XElement.Load("D:\\PersonData.Xml");
else
xe = new XElement("Users");
XElement newUser = new XElement("User");
newUser.Add(new XAttribute("idNumber", pd.IdNumber1));
newUser.Add(new XElement("Firstname", pd.FirstName1));
newUser.Add(new XElement("LastName", pd.LastName1));
newUser.Add(new XElement("DateOfBirth", pd.DateOfBirth1.ToString()));
newUser.Add(new XElement("Address", pd.Address1));
xe.Add(newUser);
xe.Save("D:\\PersonData.Xml");
try to flush like xWriter.Flush() after you write your end element?
Related
I have an xml file which is like so.
<Root>
<Child123>
more nodes inside
</Child123>
<Child123></Child123>
<Child123></Child123>
<Child123></Child123>
</Root>
My code is generating this file which is not correctly formatting its forgetting to place a hard return at only the <Cild123>. You will see on line 2 the 3 line Child123 is starting on Line 2 when it should be on Line 3?
<Root>
<Child123></Child123>
<Child123></Child123><Child123>
more nodes inside
</Child123><Child123>
more nodes inside
</Child123>
</Root>
This is my code I read the file into a list view and allow the user to pick some lines then I click generate, this then allows the above file to be generated
public static string Seralize<T>(T dataToSerlize)
{
var ns = new XmlSerializerNamespaces();
ns.Add("", "");
var seralize = new XmlSerializer(dataToSerlize.GetType());
var settings = new XmlWriterSettings();
settings.Indent = true;
settings.OmitXmlDeclaration = true;
settings.NewLineChars = "\n";
settings.NewLineHandling = NewLineHandling.Replace;
using (var stream = new StringWriter())
{
using (var test = XmlWriter.Create(stream, settings))
{
seralize.Serialize(test, dataToSerlize, ns);
return stream.ToString();
}
}
}
But as you see its not keeping the formatting correct in the generated xml file how to I ensure that it retains the flow of the first xml
PS I also tried
settings.Encoding = Encoding.UTF-8;
Which I thought may be the issue.
I also tried
settings.NewLineChars = "\n";
But still no joy.
One approach would be to focus your efforts on generating valid XML and let XDocument handle the formatting. Assuming your generated XML is valid, you can do this with it:
using System.Xml.Linq;
string rawXml =
#"<Root>
<Child123></Child123>
<Child123></Child123><Child123>
</Child123><Child123>
</Child123>
</Root>";
XDocument formattedXml = XDocument.Parse(rawXml);
The output of formattedXml.ToString() is:
<Root>
<Child123></Child123>
<Child123></Child123>
<Child123></Child123>
<Child123></Child123>
</Root>
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 have a related post asking how to select nodes from an XmlDocument using an XPath statement.
The only way I could get the SelectNodes to work was to create a non default namespace "x" and then explicitly reference the nodes in the XPath statement.
Whilst this works and provides me with a node list, the canonicalization then fails to produce any content to my selected nodes in the output.
I've tried using XmlDsigExcC14NTransform and specifying the namespace but this produces the same output.
Below is an example of the xml output produced (using the XML in my related post):
<Applications xmlns="http://www.myApps.co.uk/">
<Application>
<ApplicantDetails>
<Title>
</Title>
<Forename>
</Forename>
<Middlenames>
<Middlename>
</Middlename>
</Middlenames>
<PresentSurname>
</PresentSurname>
<CurrentAddress>
<Address>
<AddressLine1>
</AddressLine1>
<AddressLine2>
</AddressLine2>
<AddressTown>
</AddressTown>
<AddressCounty>
</AddressCounty>
<Postcode>
</Postcode>
<CountryCode>
</CountryCode>
</Address>
<ResidentFromGyearMonth>
</ResidentFromGyearMonth>
</CurrentAddress>
</ApplicantDetails>
</Application>
<Application>
<ApplicantDetails>
<Title>
</Title>
<Forename>
</Forename>
<Middlenames>
<Middlename>
</Middlename>
</Middlenames>
<PresentSurname>
</PresentSurname>
<CurrentAddress>
<Address>
<AddressLine1>
</AddressLine1>
<AddressLine2>
</AddressLine2>
<AddressTown>
</AddressTown>
<AddressCounty>
</AddressCounty>
<Postcode>
</Postcode>
<CountryCode>
</CountryCode>
</Address>
<ResidentFromGyearMonth>
</ResidentFromGyearMonth>
</CurrentAddress>
</ApplicantDetails>
</Application>
</Applications>
Another StackOverflow user has had a similar problem here
Playing around with this new code, I found that the results differ depending upon how you pass the nodes into the LoadInput method. Implementing the code below worked.
I'm still curious as to why it works one way and not another but will leave that for a rainy day
static void Main(string[] args)
{
string path = #"..\..\TestFiles\Test_1.xml";
if (File.Exists(path) == true)
{
XmlDocument xDoc = new XmlDocument();
xDoc.PreserveWhitespace = true;
using (FileStream fs = new FileStream(path, FileMode.Open))
{
xDoc.Load(fs);
}
//Instantiate an XmlNamespaceManager object.
System.Xml.XmlNamespaceManager xmlnsManager = new System.Xml.XmlNamespaceManager(xDoc.NameTable);
//Add the namespaces used to the XmlNamespaceManager.
xmlnsManager.AddNamespace("x", "http://www.myApps.co.uk/");
// Create a list of nodes to have the Canonical treatment
XmlNodeList nodeList = xDoc.SelectNodes("/x:ApplicationsBatch/x:Applications|/x:ApplicationsBatch/x:Applications//*", xmlnsManager);
//Initialise the stream to read the node list
MemoryStream nodeStream = new MemoryStream();
XmlWriter xw = XmlWriter.Create(nodeStream);
nodeList[0].WriteTo(xw);
xw.Flush();
nodeStream.Position = 0;
// Perform the C14N transform on the nodes in the stream
XmlDsigC14NTransform transform = new XmlDsigC14NTransform();
transform.LoadInput(nodeStream);
// use a new memory stream for output of the transformed xml
// this could be done numerous ways if you don't wish to use a memory stream
MemoryStream outputStream = (MemoryStream)transform.GetOutput(typeof(Stream));
File.WriteAllBytes(#"..\..\TestFiles\CleanTest_1.xml", outputStream.ToArray());
}
}
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?
I need to add the following code to the beginning of an XML file, while creating it:
<?xml version="1.0" encoding="ISO-8859-1"?>
<?xml-stylesheet type="text/xsl" href="colors.xslt"?>
I'm sure there is a method for this, but I haven't found it yet. I'm using C#.
Thank you
XmlDocument.CreateProcessingInstruction Method
public static void Main()
{
var doc = new XmlDocument();
doc.AppendChild(doc.CreateProcessingInstruction(
"xml-stylesheet",
"type='text/xsl' href='colors.xslt'"));
}
For LINQ XDocument you can use this:
XDocument xDoc = new XDocument();
xDoc.Add(new XProcessingInstruction("xml-stylesheet",
"type=\"text/xsl\" href=\"xml-style.xslt\""));