How to remove unnecessary xmlns attribute in C#? - c#

I'm trying to update an existing XML file, but always when I update it adding new tags the xmlns="" attribute mysteriously appears in all tags and I didn't find a way to remove it.
private static void EditarXML(string path, List<SiteUrl> listaUrls, bool indice, string loc)
{
XmlDocument documentoXML = new XmlDocument();
documentoXML.Load(path);
XmlNode sitemap = documentoXML.CreateElement("sitemap");
XmlNode xloc = documentoXML.CreateElement("loc");
xloc.InnerText = loc;
sitemap.AppendChild(xloc);
XmlNode lastmod = documentoXML.CreateElement("lastmod");
lastmod.InnerText = DateTime.Now.ToShortDateString();
sitemap.AppendChild(lastmod);
documentoXML.DocumentElement.AppendChild(sitemap);
}
Any help or ideas would be appreciated.

This will happen with the parent node you are appending to has a namespace, but you don't specify it in the CreateElement() call.
To handle this, you can get the namespace from the DocumentElement, like this (my sample just creates the document in memory, but the principle is the same), and pass it to CreateElement().
if (x.DocumentElement != null) {
var xmlns = (x.DocumentElement.NamespaceURI);
var sitemap = x.CreateElement("sitemap", xmlns);
var xloc = x.CreateElement("loc", xmlns);
xloc.InnerText = "Hello";
sitemap.AppendChild(xloc);
var lastmod = x.CreateElement("lastmod", xmlns);
lastmod.InnerText = DateTime.Now.ToShortDateString();
sitemap.AppendChild(lastmod);
x.DocumentElement.AppendChild(sitemap);
}
Console.WriteLine(x.InnerXml);
Output
<test xmlns="jdphenix"><sitemap><loc>Hello</loc><lastmod>4/20/2015</lastmod></sitemap></test>
Note that if I did not pass the parent namespace to each CreateElement() call, the children of that call would have the blank xmlns.
// incorrect - appends xmlns=""
if (x.DocumentElement != null) {
var sitemap = x.CreateElement("sitemap");
var xloc = x.CreateElement("loc");
xloc.InnerText = "Hello";
sitemap.AppendChild(xloc);
var lastmod = x.CreateElement("lastmod");
lastmod.InnerText = DateTime.Now.ToShortDateString();
sitemap.AppendChild(lastmod);
x.DocumentElement.AppendChild(sitemap);
}
Console.WriteLine(x.InnerXml);
Output
<test xmlns="jdphenix"><sitemap xmlns=""><loc>Hello</loc><lastmod>4/20/2015</lastmod></sitemap></test>
Related reading: Why does .NET XML append an xlmns attribute to XmlElements I add to a document? Can I stop it?
How to prevent blank xmlns attributes in output from .NET's XmlDocument?

Related

Textbox string to xml issue

I'm having a little problem formatting my xml file using C# code in a Windows Form app. Here is the code i'm using for this project:
private void btnSend_Click(object sender, EventArgs e)
{
string _name = tbName.ToString();
string _st = tbSt.ToString();
string _dx = tbDx.ToString();
string _iq = tbIq.ToString();
string _filename = #"c:\Add.xml";
if (File.Exists(_filename))
{
XDocument xDoc = XDocument.Load(_filename);
xDoc.Root.Add(new XElement("character",
new XElement("name", _name),
new XElement("st", _st),
new XElement("dx", _dx),
new XElement("iq", _iq)
));
xDoc.Save(_filename);
}
else if (!File.Exists(_filename))
{
XmlDocument doc = new XmlDocument();
XmlNode docNode = doc.CreateXmlDeclaration("1.0", "UTF-8", null);
doc.AppendChild(docNode);
XmlNode productsNode = doc.CreateElement("characters");
doc.AppendChild(productsNode);
XmlNode productNode = doc.CreateElement("character");
productsNode.AppendChild(productNode);
XmlNode nmNode = doc.CreateElement("name");
nmNode.AppendChild(doc.CreateTextNode(_name));
productNode.AppendChild(nmNode);
XmlNode stNode = doc.CreateElement("st");
stNode.AppendChild(doc.CreateTextNode(_st));
productNode.AppendChild(stNode);
XmlNode dxNode = doc.CreateElement("dx");
dxNode.AppendChild(doc.CreateTextNode(_dx));
productNode.AppendChild(dxNode);
XmlNode iqNode = doc.CreateElement("iq");
iqNode.AppendChild(doc.CreateTextNode(_iq));
productNode.AppendChild(iqNode);
doc.Save(#"c:\Add.xml");//must have to save
}
}
The problem is that my .xml file comes out with the whole TextBox class prefix attached such as this:
...
- <character>
<name>System.Windows.Forms.TextBox, Text: bob</name>
<st>System.Windows.Forms.TextBox, Text: 10</st>
<dx>System.Windows.Forms.TextBox, Text: 12</dx>
<iq>System.Windows.Forms.TextBox, Text: 08</iq>
</character>
I'd like to have it look like this:
- <character>
<name>bob</name>
<st>10</st>
<dx>12</dx>
<iq>08</iq>
</character>
If any of you fine knowledgeable folks could lend a hand (or point me a link) I'd appreciate it. I did comb through the Google but nothing turned up with this specific odd problem. Many thanks for any help you can offer.
The obvious I did not see. Thanks to those who may respond. Now that I post it, it is obvious.
Changing
string _name = tbName.ToString();
simply to
string _name = tbName.Text;
of course fixed the problem. Hope this may help someone else.

How to parse XML in a Windows Phone 7 application

Could someone tell me how to parse a XML-String that i receive from a wcf-rest service?
my webserive XML-String looks like
<WS>
<Info>
<Name>Beta</Name>
<Description>Prototyps</Description>
</Info>
<Pages>
<Page>
<Name>Custom</Name>
<Description>toDo</Description>
</Page>
...many other pages...
</Pages>
</WS>
an my phone sourcecode:
public void DownloadCompleted(Object sender, DownloadStringCompletedEventArgs e)
{
if (!e.Cancelled && e.Error == null)
{
var answer = XElement.Parse(e.Result).Descendants("WS"); // null
...
}
}
if i try to parse it through XDocument.Load(e.Result) then i get the exception: File not Found.
i just want the "unique" information of the Info-Node and a list of all Page-Nodes with their values
Update
Even if i try to load the Root-Element via var item = xdoc.Root.Descendants(); item will be assigned to the whole xml-file.
Update 2 it seems the problem occurs with the namespaces in the root-element. with namespaces xdocument will parse the webservice output not correctly. if i delete the namespaces it works fine. could someone explain me this issue? and is there a handy solution for deleting all namespaces?
update 3 A Handy way for removing namespaces1
With really simple XML if you know the format wont change, you might be interested in using XPath:
var xdoc = XDocument.Parse(e.Result);
var name = xdoc.XPathSelectElement("/WS/Info/Name");
but for the multiple pages, maybe some linq to xml
var xdoc = XDocument.Parse(xml);
var pages = xdoc.Descendants("Pages").Single();
var PagesList = pages.Elements().Select(x => new Page((string)x.Element("Name"), (string)x.Element("Description"))).ToList();
Where Page is a simple class:
public class Page
{
public string Name { get; set; }
public string Descrip { get; set; }
public Page(string name, string descrip)
{
Name = name;
Descrip = descrip;
}
}
Let me know if you need more explanation.
Also to select the Info without XPath:
var info = xdoc.Descendants("Info").Single();
var InfoName = info.Element("Name").Value;
var InfoDescrip = info.Element("Description").Value;
Viktor - XDocument.Load(string) attempts to load an XDocument by the supplied filename, not a string representation of an XML element.
You say var answer = XElement.Parse(e.Result).Descendants("WS"); // null, but which part is null? The parsed XElement or the attempt to grab a descendant? If <WS>...</WS> is your root element, would the .Descendents("WS") call return the root element? Based on the documentation for XElement.DescendantsAndSelf(), I'm guessing not. Have you instead tried calling:
var answer = XElement.Parse(e.Result).Descendants("Info");
A quick test on my end showed that, with WS as the root element, calling XElement.Parse(e.Result).Descendants("WS"); yielded no results, while XElement.Parse(e.Result).Descendants("Info"); yielded the <Info>...</Info> element.

Dash at the start of XmlAttribute in C#

I want to be able to do something like this :
//buildArgs
XmlNode buildArgs = doc.CreateElement("buildArgs");
XmlAttribute buildArgsAtt = doc.CreateAttribute("-D:project.rc_file");
But I get the fallowing error :
An unhandled exception of type 'System.ArgumentException' occurred in System.Xml.dll
Additional information: Invalid name character in '-D'. The '-' character, hexadecimal value 0x2D, cannot be included in a name.
But I did not choose the format. I am trying to automate the process of adding a new element to cruisecontrol.net config file (ccnet.config). So I need to put that dash there.
This is my code :
//create new instance of XmlDocument
XmlDocument doc = new XmlDocument();
doc.PreserveWhitespace = false;
//load from file
doc.Load(filename);
//create node and add value
XmlNode projet = doc.CreateNode(XmlNodeType.Element, "projet", null);
XmlAttribute projetAtt = doc.CreateAttribute("name");
projetAtt.Value = projectName + " " + oracleVersion;
projet.Attributes.SetNamedItem(projetAtt);
...
//buildArgs
XmlNode buildArgs = doc.CreateElement("buildArgs");
XmlAttribute buildArgsAtt = doc.CreateAttribute("-D:project.rc_file");
buildArgsAtt.Value = projectName + ".rc";
XmlAttribute buildArgsAtt2 = doc.CreateAttribute("-D:project.svn_trunk_ver");
buildArgsAtt2.Value = trunkNb;
XmlAttribute buildArgsAtt3 = doc.CreateAttribute("-D:project.svn_trunk");
buildArgsAtt3.Value = trunkPath;
buildArgs.Attributes.SetNamedItem(buildArgsAtt);
buildArgs.Attributes.SetNamedItem(buildArgsAtt2);
buildArgs.Attributes.SetNamedItem(buildArgsAtt3);
//add to parent node
projet.AppendChild(nodeWD);
projet.AppendChild(category);
projet.AppendChild(trigger);
trigger.AppendChild(intTrigger);
projet.AppendChild(sourcecontrol);
sourcecontrol.AppendChild(trunkUrl);
sourcecontrol.AppendChild(workingDirectory);
projet.AppendChild(tasks);
tasks.AppendChild(nant);
nant.AppendChild(targetList);
targetList.AppendChild(target);
nant.AppendChild(buildArgs);
//add to elements collection
doc.DocumentElement.AppendChild(projet);
XmlWriterSettings settings = new XmlWriterSettings();
settings.Indent = true;
settings.NewLineOnAttributes = true;
settings.Encoding = Encoding.UTF8;
using (XmlWriter writer = XmlTextWriter.Create(filename, settings))
{
doc.Save(writer);
}
I checked this : Using - in XML element name and others, but I didn't find an answer that I could use.
-EDIT-
This is an exemple of the ccnet.config :
http://ccnet.sourceforge.net/CCNET/Configuring%20the%20Server.html
Thanks!
You simply can't, that's not a valid attribute name. You can store it as attribute value though - just use a name that XML allows.
I'm pretty sure CruiseControl.Net is not doing this either, as it couldn't use the built-in parser on such file.
EDIT: it's element value (also called content). Set it as follows:
var buildArgs = doc.CreateElement("buildArgs");
buildArgs.Value = "-D:project.rc_file";
Which line of the example config? Do you mean this one?
<buildArgs>-D:cvs.executable=c:\putty\cvswithplinkrsh.bat</buildArgs>
That's not an attribute. It's element content.

Asp.net code not performing on actual server as localhost

I have the following code that works fine on my localhost using IIS7 but when i upload it to my server it is behaving not the same as it did on my localhost
For example the submit button when clicked should check validation which it does on my localhost and then redirects to a URL if the validation is correct
But when the same is tried on the actual server over here
The not working link
the problem started when i introduced a redirect url (in C# code is Response.Redirect("http://www.google.com");) in to the c# code...if there is a better way to do this all this hassle wont be necessary..tks
this is the code that i used
<%# Page Language="C#" Debug="true" %>
<%# Import Namespace="System.Xml" %>
<script runat="server">
protected void btnSave_Click(object sender, EventArgs e)
{
txtAddress.Text = "";
string xmlPath = MapPath("Books.xml");
XmlDocument doc = new XmlDocument();
//Check if the file already exists or not
if (System.IO.File.Exists(xmlPath))
{
doc.Load(xmlPath);
XmlNode bookNode = CreateBookNode(doc);
//Get reference to the book node and append the book node to it
XmlNode bookStoreNode = doc.SelectSingleNode("bookstore");
bookStoreNode.AppendChild(bookNode);
lblResult.Text = "XML Document has been successfully updated";
txtAddress.Text = ""; Response.Redirect("http://www.google.com");
}
else
{
XmlNode declarationNode = doc.CreateXmlDeclaration("1.0", "", "");
doc.AppendChild(declarationNode);
XmlNode comment = doc.CreateComment("This file represents a fragment of a book store inventory database");
doc.AppendChild(comment);
XmlNode bookstoreNode = doc.CreateElement("bookstore");
XmlNode bookNode = CreateBookNode(doc);
//Append the book node to the bookstore node
bookstoreNode.AppendChild(bookNode);
//Append the bookstore node to the document
doc.AppendChild(bookstoreNode);
lblResult.Text = "XML Document has been successfully created";
txtAddress.Text = "";Response.Redirect("http://www.google.com");
}
doc.Save(xmlPath);
}
XmlNode CreateBookNode(XmlDocument doc)
{
/*
XmlNode bookNode = doc.CreateElement("book");
//Add the genre attribute to the book node
XmlAttribute genreAttribute = doc.CreateAttribute("genre");
genreAttribute.Value = txtGenre.Text;
bookNode.Attributes.Append(genreAttribute);
http://www.java2s.com/Code/ASP/XML/SaveformdatatoXMLfile.htm
*/
XmlNode bookNode = doc.CreateElement("book");
//Declaration of the Main Node (Particulars)
XmlNode particularsnode = doc.CreateElement("Particulars");
//Declaration of Child Nodes in the Main Node(Particulars)
XmlNode nameNode = doc.CreateElement("Name");
XmlNode phoneNode = doc.CreateElement("Phone");
XmlNode emailNode = doc.CreateElement("Email");
XmlNode AddressNode = doc.CreateElement("Address");
//Getting the textvalue from the htmlform
nameNode.InnerText = txtName.Text;
phoneNode.InnerText = txtPhone.Text;
emailNode.InnerText = txtEmail.Text;
AddressNode.InnerText = txtAddress.Text;
//Updating the XML file here the particularsnode has various children and they are being updated
particularsnode.AppendChild(nameNode);
particularsnode.AppendChild(phoneNode);
particularsnode.AppendChild(emailNode);
particularsnode.AppendChild(AddressNode);
bookNode.AppendChild(particularsnode);
//Declaration of the Main Node (BookParticulars)
XmlNode bookparticularsnode = doc.CreateElement("BookParticulars");
//Declaration of Child Nodes in the Main Node(BookParticulars)
XmlNode schoolNode = doc.CreateElement("School");
XmlNode currentlevelNode = doc.CreateElement("CurrentLevel");
XmlNode GABDNode = doc.CreateElement("GiveAwayBookDetails");
XmlNode LRNode = doc.CreateElement("LevelRequired");
//Getting the textvalue from the htmlform
schoolNode.InnerText = txtSchool.Text;
currentlevelNode.InnerText = txtCurrentLevel.Text;
GABDNode.InnerText = txtGABD.Text;
LRNode.InnerText = txtLR.Text;
//Updating the XML file here the particularsnode has various children and they are being updated
particularsnode.AppendChild(schoolNode);
particularsnode.AppendChild(currentlevelNode);
particularsnode.AppendChild(GABDNode);
particularsnode.AppendChild(LRNode);
bookNode.AppendChild(bookparticularsnode);
return bookNode;
}
public static string NewLineToBreak(string input)
{
Regex regEx = new Regex(#"[\n|\r]+");
return regEx.Replace(input, "<br />");
}
protected void txtAddress_Load(object sender, EventArgs e)
{
txtAddress.Text = "Woodlands Drive 14\n Blk";
}
</script>
Try using Server.MapPath as describes in ASP.NET Web Project Paths or try using Page.ResolveUrl
Have you tried using fully qualified paths for the resources you're trying to load?
e.g.:
string xmlPath = MapPath("~/Books.xml");
-or-
string xmlPath = MapPath("~/<some_sub_dir>/Books.xml");
Also, is your production server throwing exceptions? If so, displaying them locally only and using a local http session to see them might help.
example web.config section for customerrors:
<customErrors mode="RemoteOnly" defaultRedirect="GenericErrorPage.htm">
<error statusCode="403" redirect="NoAccess.htm" />
<error statusCode="404" redirect="FileNotFound.htm" />
</customErrors>
Try giving the fully qualified path and see if its picking the XML file. I am sure it might be some path issue that is causing the exception. Also make sure you turn on the Custom Errors mode so that you can see the error.

XML Replace in c#

Im trying to use the ReplaceChild function. the code works, and no exceptions are thrown, but when I print XML to the screen it seems as if the function didnt work. the original node is the but not the new one.
private void convertClubComp(XmlDocument doc)
{
XmlNode sessionNode = doc.SelectSingleNode("Session");
XmlNode clubsNode = doc.CreateNode(XmlNodeType.Element, "Clubs", "");
XmlNode playerNode = sessionNode.SelectSingleNode("Players").SelectSingleNode("Player");
XmlNode groupNode = sessionNode.SelectSingleNode("Players").SelectSingleNode("Player").SelectSingleNode("Groups");
Console.WriteLine(playerNode.Name);
clubsNode = doc.ImportNode(groupNode, true);
playerNode.ReplaceChild(clubsNode, sessionNode.SelectSingleNode("Players").SelectSingleNode("Player").SelectSingleNode("Groups"));
Console.WriteLine(clubsNode.FirstChild.FirstChild.Name);
Console.WriteLine("!"+playerNode.FirstChild.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.Name);
}
Thanks
Ok, what's happening is when you do the ImportNode() it is replacing your reference to the new node you created with a clone of the other node. I think what you're looking for is something along the lines of this:
private void convertClubComp(XmlDocument doc)
{
XmlNode sessionNode = doc.SelectSingleNode("Session");
XmlNode playerNode = sessionNode.SelectSingleNode("Players").SelectSingleNode("Player");
XmlNode groupNode = playerNode.SelectSingleNode("Groups");
Console.WriteLine(playerNode.Name);
XmlNode clubsNode = doc.CreateElement("Clubs", "");
foreach (XmlNode child in groupNode.ChildNodes)
{
clubsNode.AppendChild(child.CloneNode(true));
}
foreach (XmlAttribute attribute in groupNode.Attributes)
{
clubsNode.Attributes.Append((attribute.Clone() as XmlAttribute));
}
playerNode.ReplaceChild(clubsNode, groupNode);
Console.WriteLine(clubsNode.FirstChild.FirstChild.Name);
Console.WriteLine("!" + playerNode.FirstChild.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.Name);
}
On a separate note, don't use SelectSingleNode() or SelectNodes() if you already have a reference. It's really poor practice and in larger systems can kill your performance.

Categories