I have the following XML File,
<?xml version="1.0"?>
<MainClass xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Items>
<Settings xsi:type="FileModel">
<Name>FileRepository</Name>
<IsActive>true</IsActive>
<IsHidden>false</IsHidden>
</Settings>
<Settings xsi:type="ServerModel">
<Name>DelRep</Name>
<IsActive>false</IsActive>
<IsHidden>false</IsHidden>
</Settings>
</Items>
<DirectoryPath>D:\MainFolder</DirectoryPath>
</MainClass>
This XML File stored above in a string as string wholeContent = File.ReadAllText(this.FilePath);
where this FilePath has a valid path to the location of the file .
the wholeContent stores the entire XML which I later use but now I have the necessity to obtain the path stores as a string within the <DirectoryPath> . Is there a way I can do this using wholeContent or what would be the appropriate approach ?
I would recommend not to load the XML document as string, use the types provided by .NET, such as XDocument.
Accessing the elements and their values gets very easy that way:
XDocument document = XDocument.Load(this.FilePath);
var element = document.Root.Elements().Single(x => x.Name == "DirectoryPath");
var directoryPath = element.Value;
Related
I have an XML file. I want C # with the desktop application. There are similar solutions on the site. But I can't read with the XML I have. How should I proceed about this?
<?xml version="1.0"?>
<RealTimeMetrics SiteId="Site ID">
<Properties>
<Version>3</Version>
<TransmitTime>1581582053</TransmitTime>
<MacAddress>00:b0:9d:23:72:f0</MacAddress>
<IpAddress>192.168.1.99</IpAddress>
<HostName>Cam-19100400</HostName>
<HttpPort>80</HttpPort>
<HttpsPort>443</HttpsPort>
<Timezone>3</Timezone>
<TimezoneName>(GMT 03:00) Nairobi</TimezoneName>
<DST>0</DST>
<HwPlatform>2500</HwPlatform>
<SerialNumber>19100400</SerialNumber>
<DeviceType>0</DeviceType>
<SwRelease>4.1.4005.2249</SwRelease>
</Properties>
<RTReport Date="2020-02-13T11:20:53">
<RTObject Id="0" DeviceId="Demo" Devicename="Demo" ObjectType="0" Name="TEST">
<RTCount TotalEnters="0" TotalExits="0"/>
</RTObject>
</RTReport>
</RealTimeMetrics>
I used simple solution to read and edit XML file:
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load("path\to\file.xml");
XmlNode node = xmlDoc.SelectSingleNode("//nodeName");
node.InnerText = value;
xmlDoc.Save("path\to\file.xml");
You can load this file, read single node or all nodes, change value of InnerText or Add Atributes, end save this file
Trying to read XML file with nested XML object with own XML declaration. As expected got exception:
Unexpected XML declaration. The XML declaration must be the first node in the document, and no white space characters are allowed to appear before it.
How can i read that specific element as text and parse it as separate XML document for later deserialization?
<?xml version="1.0" encoding="UTF-8"?>
<Data>
<Items>
<Item>
<Target type="System.String">Some target</Target>
<Content type="System.String"><?xml version="1.0" encoding="utf-8"?><Data><Items><Item><surname type="System.String">Some Surname</surname><name type="System.String">Some Name</name></Item></Items></Data></Content>
</Item>
</Items>
</Data>
Every approach i'm trying fail due to declaration exception.
var xml = System.IO.File.ReadAllText("Info.xml");
var xDoc = XDocument.Parse(xml); // Exception
var xmlDoc = new XmlDocument();
xmlDoc.LoadXml(xml); // Exception
var xmlReader = XmlReader.Create(new StringReader(xml));
xmlReader.ReadToFollowing("Content"); // Exception
I have no control over XML creation.
The only way I would know is by getting rid of the illegal second <?xml> declaration. I wrote a sample that will simply look for and discard the second <?xml>. After that the string has become valid XML and can be parsed. You may need to tweak it a bit to make it work for your exact scenario.
Code:
using System;
using System.Xml;
public class Program
{
public static void Main()
{
var badXML = #"<?xml version=""1.0"" encoding=""UTF-8""?>
<Data>
<Items>
<Item>
<Target type=""System.String"">Some target</Target>
<Content type=""System.String""><?xml version=""1.0"" encoding=""utf-8""?><Data><Items><Item><surname type=""System.String"">Some Surname</surname><name type=""System.String"">Some Name</name></Item></Items></Data></Content>
</Item>
</Items>
</Data>";
var goodXML = badXML.Replace(#"<Content type=""System.String""><?xml version=""1.0"" encoding=""utf-8""?>"
, #"<Content type=""System.String"">");
var xmlDoc = new XmlDocument();
xmlDoc.LoadXml(goodXML);
XmlNodeList itemRefList = xmlDoc.GetElementsByTagName("Content");
foreach (XmlNode xn in itemRefList)
{
Console.WriteLine(xn.InnerXml);
}
}
}
Output:
<Data><Items><Item><surname type="System.String">Some Surname</surname><name type="System.String">Some Name</name></Item></Items></Data>
Working DotNetFiddle: https://dotnetfiddle.net/ShmZCy
Perhaps needless to say: all of this would not have been needed if the thing that created this invalid XML would have applied the common rule to wrap the nested XML in a <![CDATA[ .... ]]> block.
The <?xml ...?> processing declaration is only valid on the first line of an XML document, and so the XML that you've been given isn't well-formed XML. This will make it quite difficult to parse as is without either changing the source document (and you've indicated that's not possible) or preprocessing the source.
You could try:
Stripping out the <?xml ?> instruction with regex or string manipulation, but the cure there may be worse than the disease.
The HTMLAgilityPack, which implements a more forgiving parser, may work with an XML document
Other than that, the producer of the document should look to produce well-formed XML:
CDATA sections can help this, but be aware that CDATA can't contain the ]]> end tag.
XML escaping the XML text can work fine; that is, use the standard routines to turn < into < and so forth.
XML namespaces can also help here, but they can be daunting in the beginning.
I try to export a list of object(type of "Doctor") to an xml file in c#.
It compiles and runs, but the file I get isn't correct. Can someone please can tell me what I did incorrect?
the code is:
public static void exportAsXml(string fileName, List<Entity> ListOfEntity)
{
FileInfo file = new FileInfo(fileName + ".xml");
StreamWriter sw = file.AppendText();
System.Xml.Serialization.XmlSerializer writer = new System.Xml.Serialization.XmlSerializer(typeof(Doctor));
foreach (Entity e in ListOfEntity)
{
writer.Serialize(sw,e as Doctor);
}
sw.Close();
}
the xml file is:
<?xml version="1.0" encoding="utf-8"?>
<Doctor xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<ID>87587579</ID>
<FirstName>Dan</FirstName>
<LastName>Adi</LastName>
<Gender>male</Gender>
<Salary>15000</Salary>
</Doctor><?xml version="1.0" encoding="utf-8"?>
<Doctor xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<ID>302342246</ID>
<FirstName>Lital</FirstName>
<LastName>Gal</LastName>
<Gender>female</Gender>
<Salary>25600</Salary>
</Doctor><?xml version="1.0" encoding="utf-8"?>
<Doctor xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<ID>205992457</ID>
<FirstName>Yaron</FirstName>
<LastName>Mor</LastName>
<Gender>male</Gender>
<Salary>10000</Salary>
</Doctor>
Thanks!
First of all, the resulting xml violates 2 core rules.
Xml file should have only one <?xml version="1.0" encoding="utf-8"> declaration
All your xml should be enclosed inside one root file.
In other words, in loop you generate a separate, fully-fledged xml file for each item.
Try this
var writer = new System.Xml.Serialization.XmlSerializer(typeof(List<Doctor>));
writer.Serialize(sw, ListOfEntity);
You are corrupting the xml file by serializing the doctor objects and saving it to the same file using file.AppendText();, generating corrupted xml with multiple <?xml version="1.0" encoding="utf-8"?> declarations as consequence.
You should serialize the List<Doctor> instead of serializing each doctor alone and modifying the xml file by appending text.
If you want to modify a serialized object saved inside a file, you need to deserialize the file into an object, modify it and then replace the file with the new serialized object. you cannot simply append it.
When I try to load a XML file after deleting an Element from the file, it shows the following error: Unexpected XML declaration. The XML declaration must be the first node in the document, and no white space characters are allowed to appear before it. Line 9, position 10. What is wrong with my code?
This is my XML file:
<?xml version="1.0" encoding="UTF-8"?>
<data>
<booze>booze1</booze>
<booze>booze2</booze>
<booze>booze3</booze>
<booze>booze4</booze>
</data>
And my code:
using (IsolatedStorageFile file = IsolatedStorageFile.GetUserStoreForApplication())
{
using (IsolatedStorageFileStream stream = new IsolatedStorageFileStream("favorites.xml", FileMode.Open, file))
{
XDocument xDoc = XDocument.Load(stream, LoadOptions.None);
// delete node
xDoc.Descendants("data").Elements("booze").Where(x => x.Value == favorite).DescendantsAndSelf().Remove();
xDoc.Save(stream);
}
}
My guess is that when you run the code for the first time, the delete succeeds and your XDoc contains :
<?xml version="1.0" encoding="utf-8"?>
<data>
<booze>booze1</booze>
<booze>booze2</booze>
<booze>booze4</booze>
</data>
, but when calling XDoc.Save you simply append this to the favorites.xml file. After that, the favorites.xml file contains something like this:
<?xml version="1.0" encoding="UTF-8"?>
<data>
<booze>booze1</booze>
<booze>booze2</booze>
<booze>booze3</booze>
<booze>booze4</booze>
</data><?xml version="1.0" encoding="utf-8"?>
<data>
<booze>booze1</booze>
<booze>booze2</booze>
<booze>booze4</booze>
</data>
That is why all the subsequent file loads throw the error. What you should do is overwrite the file, and not append to it. The first way of doing that that comes to mind is to close the stream, open it with Mode.Truncate and then save the XDoc. Or you can delete and recreate the file. I am not that familiar with IsolatedStorageFiles so this is a wild guess.
I have a folder full of xml files. In these files many of them share a common attribute (Name), but have a secondary attribute that is different. I want to get a list of the unique entries based off reading these xml files. Below is an example of what the various xml files will contain.
File 1
<?xml version="1.0" encoding="UTF-8"?>
<results date="2013-12-29">
<A uniqueId="1234" Name="My-Machine"/>
<error number="555">
<description><![CDATA[House on Fire]]></description>
</error>
</results>
File 2
<?xml version="1.0" encoding="UTF-8"?>
<results date="2013-12-29">
<A uniqueId="1234" Name="My-Machine"/>
<error number="556">
<description><![CDATA[House in flood]]></description>
</error>
</results>
File 3
<?xml version="1.0" encoding="UTF-8"?>
<results date="2013-12-29">
<A uniqueId="1234" Name="My-Machine"/>
<error number="556">
<description><![CDATA[House in flood]]></description>
</error>
</results>
I need to be able to read all the files, add each Name and description to a list (or possibly array). Output from example would look like this:
Name="MyMachine", description="![CDATA[House is flooding]]";
Name="MyMachine", description="![CDATA[House on fire]]";
Name="MyMachine", description="![CDATA[House on fire]]";
It seems LINQ may be the best way to handle this since the files are very small in content.
Here is a way to read that description element content from one file:
var xDoc = XDocument.Load("Input.xml");
var name = "My-Machine";
var aElement = xDoc.Root.Element("A");
string description = null;
if ((string)aElement.Attribute("Name") == name)
description = (string)xDoc.Root.Element("error").Element("description");
It will return the element value when Name attribute value matches your name variable. Otherwise description will be null.