I am using a StreamReader to read a XML file.
From that, how to get particular content in the file?
C# code I'm using:
using (StreamReader streamreader = new StreamReader(inputxmlfile))
{
string doc = streamreader.ReadLine();
while (doc != null)
{
if (content.Contains("sxnum"))
{
// How to get the 'sxnum' attribute value?
}
doc = streamreader.ReadLine();
}
}
Here what the XML file looks like:
<?xml version="1.0" encoding="UTF-8"?>
<catalog>
<cd nominee ="1 2 First" sxnum="63828910">
<title company="Grammy" price="10.20">1999 Grammy Nominees</title>
<artist all="type">Many</artist>
<country>USA</country>
.....
</catalog>
The desired output in this case is:
63828910
If the XML document is bigger and you want to process it without loading it all into memory at once, you can use the XmlReader class which can move through the xml document node by node without loading the whole document into memory.
using (StreamReader streamReader = new StreamReader(inputxmlfile))
{
// Create the xmlReader using the streamReader as a source
using (XmlReader xmlReader = XmlReader.Create(streamReader))
{
// While there are element nodes with the name "cd", go to the next cd element
while (xmlReader.ReadToFollowing("cd"))
{
// Get the value of the sxnum attribute at the current element
// and output it when present
string sxnum = xmlReader.GetAttribute("sxnum");
if (!string.IsNullOrEmpty(sxnum))
{
Console.WriteLine(sxnum);
}
}
}
}
Related
Xml File :
<?xml version="1.0" encoding="iso-8859-1"?>
<ResDoc>
<Summary>
My name is Magesh
</Summary>
</ResDoc>
How to find the data "Magesh" inside Summary tag and replace it as "GivenName".
A c# code to load XML file, find and replace.
I have tried to loading xml file using XMLDocument, find and replace. But it is not expected.
xdoc = new XmlDocument {PreserveWhitespace = true};
xdoc.LoadXml(taggedresume);
string Name1 = "Magesh";
foreach (XmlNode var in xdoc.SelectSingleNode("//ResDoc/summary"))
{
var.InnerXml.Replace(Name1, "GivenName");
}
static void Main(string[] args)
{
string xml = #"<?xml version=""1.0"" encoding=""iso-8859-1""?>
<ResDoc>
<Summary>
My name is Magesh
</Summary>
</ResDoc>";
XDocument doc = XDocument.Parse(xml);
var element = doc.Element("ResDoc").Element("Summary");
element.Value = element.Value.Replace("Magesh", "YourName");
Console.WriteLine(element.Value);
Console.ReadKey();
}
Here an example, next time try something by yourself first. You need to have reference to System.Xml.Linq;
I have the following xml:
<?xml version="1.0" encoding="utf-16" standalone="yes"?>
<property_set_list xmlns="myNamespace">
<property_set symbol_id="Config">
</property_set>
</property_set_list>
I want to open it, add some property then close it and edit the added property and then save again:
var xws = new XmlWriterSettings { Indent = true, IndentChars = TAB };
using (var reader = ReaderCreator())
using (var output = OutputCreator())
using (var xmlWriter = XmlWriter.Create(output, xws))
{
XDoc = XElement.Load(reader, LoadOptions.None);
Namespace = "myNamespace";
// Append node
AppendToNode("Config", "", MAIN_LOBBY_LIST_CTRL_LOCAL_TABLES_COLOR,
318, 8);
XDoc.Save(xmlWriter);
// Edit added node
SetColors();
// Error here
XDoc.Save(xmlWriter);
}
The property is added. Then saved successfully. Edited Successfully. But I receive the following error on the second save :
"Token StartDocument in state End Document would result in an invalid XML document."
What can I do here ? Any suggestions are welcome.
You have to create another XmlWriter. There is no way to reset it and start writing again from the begining of underlying stream.
I have a zip file that contains an xml file,
I'm Loading this xml file to an xml document without having to extract the file.
this is done via a stream.
after doing so, I'm modifying the inner text of some nodes.
The Problem is that I'm getting the previous mentioned exception after trying to save the stream, here's the code:
(I'm using DotNetZip here)
ZipFile zipFile = ZipFile.Read(zipPath); // the path is my desktop
foreach (ZipEntry entry in zipFile)
{
if (entry.FileName == "myXML.xml")
{
//creating the stream and loading the xml doc from the zip file:
Stream stream = zipFile[entry.FileName].OpenReader();
XmlReader xReader = XmlReader.Create(stream);
XmlDocument xDoc = new XmlDocument();
xDoc.Load(xReader);
//changing the inner text of the doc nodes:
xDoc.DocumentElement.SelectSingleNode("Account/Name").InnerText = "VeXe";
xDoc.DocumentElement.SelectSingleNode("Account/Money").InnerText = "Million$";
xDoc.Save(stream); // here's where I got the exception.
break;
}
}
I'm not a pro coder, but instead of xDoc.Save(stream); I noticed that it could also take a XmlWriter as a parameter, so I tried making an instance of the XmlWriter immediately after instantiating the XmlReader ..
I tried doing this: xDoc.Save(XmlWriter)
I got an exception saying something like: "Cannot Write After Reading"
how can I successfully save the xDoc ?
ADDED:
I had an idea of saving the xml file in some other place, like a temp folder or something
then adding that saved file in the zip overwriting the old one, then deleting the xml file in the temp ..
but that's not what i want, I want to deal directly with the zip file, in and out, no third parties.
You're attempting to write to the same Stream you've opened it with. You cannot do that.
Perhaps try something like this:
ZipFile zipFile = ZipFile.Read(zipPath); // the path is my desktop
foreach (ZipEntry entry in zipFile)
{
if (entry.FileName == "myXML.xml")
{
//creating the stream and loading the xml doc from the zip file:
using (Stream stream = zipFile[entry.FileName].OpenReader()) {
XmlReader xReader = XmlReader.Create(stream);
XmlDocument xDoc = new XmlDocument();
xDoc.Load(xReader);
}
//changing the inner text of the doc nodes:
xDoc.DocumentElement.SelectSingleNode("Account/Name").InnerText = "VeXe";
xDoc.DocumentElement.SelectSingleNode("Account/Money").InnerText = "Million$";
using (StreamWriter streamWriter = new StreamWriter(pathToSaveTo)) {
xDoc.Save(streamWriter);
break;
}
}
}
A quick look at the docs leads me to believe that you should do it something like this:
using(ZipFile zipFile = ZipFile.Read(zipPath))
foreach (ZipEntry entry in zipFile)
{
if (entry.FileName == "myXML.xml")
{
XmlDocument xDoc = new XmlDocument();
//creating the stream and loading the xml doc from the zip file:
using(Stream stream = zipFile[entry.FileName].OpenReader())
using(XmlReader xReader = XmlReader.Create(stream))
{
xDoc.Load(xReader);
}
//changing the inner text of the doc nodes:
xDoc.DocumentElement.SelectSingleNode("Account/Name").InnerText = "VeXe";
xDoc.DocumentElement.SelectSingleNode("Account/Money").InnerText = "Million$";
using(var ms=new MemoryStream())
using(var sw=new StreamWriter(ms))
{
xDoc.Save(sw);
sw.Flush();
ms.Position=0;
zipFile.UpdateEntry(entry.FileName,ms);
}
break;
}
}
I am getting "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" error while trying to load xml. Both my C# code and contents of XML file are given below. XML definition exists in Line 6 of the xml file and hence the error.
I can not control what's there in the xml file so how can I edit/rewrite it using C# such that xml declaration comes first and then the comments to load it without any error!
//xmlFilepath is the path/name of the xml file passed to this function
static function(string xmlFilepath)
{
XmlReaderSettings readerSettings = new XmlReaderSettings();
readerSettings.IgnoreComments = true;
readerSettings.IgnoreWhitespace = true;
XmlReader reader = XmlReader.Create(XmlFilePath, readerSettings);
XmlDocument xml = new XmlDocument();
xml.Load(reader);
}
XmlDoc.xml
<!-- Customer ID: 1 -->
<!-- Import file: XmlDoc.xml -->
<!-- Start time: 8/14/12 3:15 AM -->
<!-- End time: 8/14/12 3:18 AM -->
<?xml version="1.0" encoding="ISO-8859-1" standalone="yes"?>
-----
As the error states, the first five characters of an XML document should be <?xml. No ifs, ands or buts. The comments you have above the opening XML tag are illegal; they must go inside the XML tag (because the comment structure is itself defined by the XML standard and so is meaningless outside the main XML tags).
EDIT: Something like this should be able to rearrange the rows, given the file format from the OP:
var lines = new List<string>();
using (var fileStream = File.Open(xmlFilePath, FileMode.Open, FileAccess.Read))
using(var reader = new TextReader(fileStream))
{
string line;
while((line = reader.ReadLine()) != null)
lines.Add(line);
}
var i = lines.FindIndex(s=>s.StartsWith("<?xml"));
var xmlLine = lines[i];
lines.RemoveAt(i);
lines.Insert(0,xmlLine);
using (var fileStream = File.Open(xmlFilePath, FileMode.Truncate, FileAccess.Write)
using(var writer = new TextWriter(fileStream))
{
foreach(var line in lines)
writer.Write(line);
writer.Flush();
}
That is not valid XML.
As the error clearly states, the XML declaration (<?xml ... ?>) must come first.
I'm using the following function to remove whitespace from xml:
public static void DoRemovespace(string strFile)
{
string str = System.IO.File.ReadAllText(strFile);
str = str.Replace("\n", "");
str = str.Replace("\r", "");
Regex regex = new Regex(#">\s*<");
string cleanedXml = regex.Replace(str, "><");
System.IO.File.WriteAllText(strFile, cleanedXml);
}
Don't put any comments in the beginning of your file!
I'm reading a file like from the web:
<?xml version='1.0' encoding='UTF-8'?>
<eveapi version="2">
<currentTime>2011-07-30 16:08:53</currentTime>
<result>
<rowset name="characters" key="characterID" columns="name,characterID,corporationName,corporationID">
<row name="Conqrad Echerie" characterID="91048359" corporationName="Federal Navy Academy" corporationID="1000168" />
</rowset>
</result>
<cachedUntil>2011-07-30 17:05:48</cachedUntil>
</eveapi>
im still new to XML and i see there are many ways to read XML data, is there a certain way im going to want to do this? what i want to do is load all the data into a StreamReader? and then use get; set; to pull the data later?
If you want object-based access, put the example xml in a file and run
xsd.exe my.xml
xsd.exe my.xsd /classes
this will create my.cs which is an object model similar to the xml that you can use with XmlSerializer:
var ser = new XmlSerializer(typeof(eveapi));
var obj = (eveapi)ser.Deserialize(source);
Use XmlReader Class or XmlTextReader Class
http://msdn.microsoft.com/en-us/library/aa720470(v=vs.71).aspx
http://msdn.microsoft.com/en-us/library/system.xml.xmltextreader(v=vs.71).aspx
If you need to use the data in the easy way, especially when you're new to XML, use XmlDocument.
To load the document:
using System.Xml;
using System.IO;
public class someclass {
void somemethod () {
//Initiate the XmlDocument object
XmlDocument xdoc;
//To load from file
xdoc.Load("SomeFolder\\SomeFile.xml");
//Or to load from XmlTextReader, from a file for example
FileStream fs = FileStream("SomeFolder\\SomeFile.xml", FileMode.Open, FileAccess.Read);
XmlTextReader reader = new XmlTextReader(fs);
xdoc.Load(reader);
//In fact, you can load the stream directly
xdoc.Load(fs);
//Or, you can load from a string
xdoc.LoadXml(#"<rootElement>
<element1>value1</element1>
<element2>value2</element2>
</rootElement>");
}
}
I personally find XmlDocument far easier to use for navigating an Xml file.
To use it efficiently, you need to learn XPath. For example, to get the name of the first row:
string name = xdoc.SelectSingleNode("/eveapi/result/rowset/row").Attribute["name"].InnerText;
or even more XPath:
string name = xdoc.SelectSingleNode("/eveapi/result/rowset/row/#name").InnerText;
you can even filter:
XmlNodeList elems = xdoc.SelectNodes("//*[#name=\"characters\"]")
gives you the rowset element.
But that's off topic.