Get rid of xmlns attribute when adding node to existing xml - c#

I have an XML-file:
<ns2:root xmlns:ns2="namespace">
<ns2:a>
<ns2:b>some content</b>
<ns2:c>some content</c>
<ns2:d>some content</d>
</a>
</root>
I need to add a new node in the specific place, my code is:
var doc = XDocument.Load(file);
XNamespace ns2 = "namespace";
doc.Element(ns2 + "root").Element(ns2 + "a").Element(ns2 + "c").AddAfterSelf(
new XElement(ns2+"new",
new XElement("new1",
new XElement("new2","some content"),
new XElement("new3", "some content"))));
The output is:
<ns2:root xmlns:ns2="namespace">
<ns2:a>
<ns2:b>some content</b>
<ns2:c>some content</c>
<ns2:new>
<new1 xmlns="">
<new2>some content</new2>
<new3>some content</new3>
</new1>
</new>
<ns2:d>some content</d>
</a>
</root>
Desired output is:
<ns2:root xmlns:ns2="namespace">
<ns2:a>
<ns2:b>some content</b>
<ns2:c>some content</c>
<ns2:new>
<new1>
<new2>some content</new2>
<new3>some content</new3>
</new1>
</new>
<ns2:d>some content</d>
</a>
</root>
How can I avoid adding xmlns atrribute to the node new1?
Edited mistake in desired output.

Add "ns2 +" before every element name that needs to be in the sitemap namespace
var doc = XDocument.Load(file);
XNamespace ns2 = "namespace";
doc.Element(ns2 + "root").Element(ns2 + "a").Element(ns2 + "c").AddAfterSelf(
new XElement(ns2+"new",
new XElement(ns2+"new1",
new XElement(ns2+"new2","some content"),
new XElement(ns2+"new3", "some content"))));

Adding a default namespace before element resolved my issue
XNamespace defaultNs = "http://www.iata.org/IATA/2007/00";
target.AddAfterSelf(new XElement(defaultNs + "Suffix", suffix));

Related

XmlDocument loping (foreach) reomving NameSpace "xmlns"

hey guys I had XML file and I was using XDocument to write on it and using the next void remove the namespace
string path = Server.MapPath(xmlpath);
XDocument doc = XDocument.Load(path)
XElement root = new XElement("url");
foreach (var node in doc.Root.Descendants()
.Where(n => n.Name.NamespaceName == ""))
{
node.Attributes("xmlns").Remove();
node.Name = node.Parent.Name.Namespace + node.Name.LocalName;
}
this function works 100% with the XDocument now I changed
XDocument oldDoc = XDocument.Load(path);// the old doucument
XmlDocument newDoc = new XmlDocument();//the new document
I need a function that allows me to make loping and remove the namespace xmlns from my nodes the same one like above thanks a lot for your time's guys and thanks a lot for reading my question
You were very close, just had to use XMLDocument.CreateElement(string Name) overload which returns a XMLNode and then use .InnerText property to set your value
var mainRoot = doc.DocumentElement; //urlset element
var urlRoot = doc.CreateElement("url"); //create url element
var VidooTree = urlRoot.AppendChild(doc.CreateElement(a, ""));
urlRoot.AppendChild(doc.CreateElement("loc", "http:/domain/site.com"));
VidooTree.AppendChild(doc.CreateElement(b)).InnerText="imgur";
VidooTree.AppendChild(doc.CreateElement(c)).InnerText= "videoTitle";
VidooTree.AppendChild(doc.CreateElement("video:description")).InnerText= "videoDec";
VidooTree.AppendChild(doc.CreateElement(d)).InnerText= "VideoApi";
VidooTree.AppendChild(doc.CreateElement(m)).InnerText= "duration";
VidooTree.AppendChild(doc.CreateElement(nn)).InnerText= "2050-11-05T19:20:30+08:00";
VidooTree.AppendChild(doc.CreateElement(e)).InnerText= "watched";
VidooTree.AppendChild(doc.CreateElement(k)).InnerText= "date";
VidooTree.AppendChild(doc.CreateElement(f)).InnerText= "yes";
VidooTree.AppendChild(doc.CreateElement(g)).InnerText="No";
VidooTree.AppendChild(doc.CreateElement(h)).InnerText= "VideoKindName";
urlRoot.AppendChild(VidooTree);
mainRoot.AppendChild(urlRoot);
Output
<url xmlns="">
<loc xmlns="http:/domain/site.com" />
<video>
<thumbnail_loc>imgur</thumbnail_loc>
<title>videoTitle</title>
<description>videoDec</description>
<content_loc>VideoApi</content_loc>
<duration>duration</duration>
<expiration_date>2050-11-05T19:20:30+08:00</expiration_date>
<view_count>watched</view_count>
<publication_date>date</publication_date>
<family_friendly>yes</family_friendly>
<live>No</live>
<category>VideoKindName</category>
</video>
</url>

Why xmlns appears at the parents' node in DGML file writing?

When I save a DGML file, unnecessary XNamespace appears.
This is a code of saving DGML file.
public void saveDGMLFile()
{
Debug.Log("Save DGML file!");
XNamespace xNamespace = "http://schemas.microsoft.com/vs/2009/dgml";
xDoc = new XDocument();
XElement root = new XElement(
xNamespace + "DirectedGraph",
new XAttribute("name", "root"));
xDoc.Add(root);
XElement parent = xDoc.Root;
XElement nodes = new XElement("Nodes");
foreach (var e in exploded_positions)
{
XElement item = new XElement("Node");
item.SetAttributeValue("Id", e.Item1.name);
item.SetAttributeValue("Category", 0);
item.SetAttributeValue(XmlConvert.EncodeName("start_position"), (e.Item2.x + " " + e.Item2.y + " " + e.Item2.z));
item.SetAttributeValue(XmlConvert.EncodeName("end_position"), (e.Item3.x + " " + e.Item3.y + " " + e.Item3.z));
nodes.Add(item);
}
parent.Add(nodes);
XElement links = new XElement("Links");
XElement link = new XElement("Link");
links.Add(link);
parent.Add(links);
XElement categories = new XElement("Categories");
XElement category = new XElement("category");
categories.Add(category);
parent.Add(categories);
xDoc.Save(outputFileName);
}
And this is an output DGML file.
<?xml version="1.0" encoding="utf-8"?>
<DirectedGraph name="root" xmlns="http://schemas.microsoft.com/vs/2009/dgml">
<Nodes xmlns="">
<Node Id="PTC_EXP_Blasensensor-Adapter-+-" Category="0" start_position="0 0 0" end_position="0 0 -0.7573751" />
<Node Id="PTC_EXP_BML_Mutter_UNF-2B_1-14-" Category="0" start_position="0 0 0" end_position="0 0.7573751 0" />
<Node Id="PTC_EXP_BUSAKSHAMBAN_OR1501300N" Category="0" start_position="0 0 0" end_position="0.7573751 0 0" />
</Nodes>
<Links xmlns="">
<Link />
</Links>
<Categories xmlns="">
<category />
</Categories>
</DirectedGraph>
As you can see, xmlns="" of XNameSpace appears after the parents' node, Nodes, Links, and Categories.
How can I remove it?
It's because when you set the namespace on the root element to http://schemas.microsoft.com/vs/2009/dgml, it's only affecting that element, it doesn't become the default for the whole document - child elements you add to it will still have a default/empty namespace.
That's why, when the XML is output those elements have the xmlns attribute to distinguish that they are not in the same namespace.
To change that, when creating the child elements you can add the namespace as you have done for the DirectedGraph root element - for example:
XElement nodes = new XElement(xNamespace + "Nodes");
Once they have the same element as the root node, they will no longer be output with an empty xmlns attribute.
Alternatively, see here for a method to do that for all child nodes in a document.

Need Help About the Xml File generated by my code

Below is my controller Code which generate the XML file and save this file and specific location
List<propertyfile> data = ws.GetPropertyFiles();
XmlDocument writer = new XmlDocument();
// Create XML declaration
XmlNode declaration = writer.CreateNode(XmlNodeType.XmlDeclaration, null, null);
writer.AppendChild(declaration);
// Make the root element first
XmlElement root = writer.CreateElement("Channel");
writer.AppendChild(root);
//XmlElement rot = writer.CreateElement("item");
//writer.AppendChild(rot);
//Server.MapPath //HttpContext.Current.Server.MapPath("~")
string wallFolderPath = Server.MapPath("~/assets/wall/");
var newGuid = Guid.NewGuid().ToString();
string filename = wallFolderPath+ "wallview_" +newGuid+".xml";
var pathlocal = ServerUrlPath+"assets/wall/" + "wallview_" + newGuid + ".xml";
ViewBag.wallpath = pathlocal;
System.IO.File.Create(filename).Dispose();
foreach (var a in data)
{
if (a.Path != null && a.ThumbnailPath != null)
{
XmlElement id = writer.CreateElement("item");
XmlElement name = writer.CreateElement("title");
name.InnerText = a.Name;
XmlElement age = writer.CreateElement("media:description");
var e_path = a.Path;
XmlElement anchor = writer.CreateElement("a");
e_path = e_path.Substring(2, e_path.Length - 2);
e_path= ServerUrlPath + e_path;
anchor.SetAttribute("href", e_path);
age.AppendChild(anchor);
//age.SetAttribute("href", e_path);
XmlElement linq = writer.CreateElement("link");
var e_linq = a.Path;
e_linq = e_linq.Substring(2, e_linq.Length - 2);
linq.InnerText = ServerUrlPath + e_linq;
XmlElement thumb = writer.CreateElement("media:thumbnail");
var e_thumbnail = a.ThumbnailPath;
e_thumbnail = e_thumbnail.Substring(2, e_thumbnail.Length - 2);
e_thumbnail = ServerUrlPath + e_thumbnail;
thumb.SetAttribute("url", e_thumbnail);
XmlElement content = writer.CreateElement("media:content");
content.SetAttribute("url", e_thumbnail);
id.AppendChild(name);
id.AppendChild(age);
id.AppendChild(linq);
id.AppendChild(thumb);
id.AppendChild(content);
root.AppendChild(id);
writer.AppendChild(root);
}
}
writer.Save(filename);
Result(XML File Generated)
<Channel>
<item>
<title>RedbrushAlpha.png</title>
<description>
<a href="http://localhost:2023/Files/aa1989f3-f4bd-489d-abca-b0c7cdfa4ae7.png"/>
</description>
<link>
http://localhost:2023/Files/aa1989f3-f4bd-489d-abca-b0c7cdfa4ae7.png
</link>
<thumbnail url="http://localhost:2023/FilesThumbs/aa1989f3-f4bd-489d-abca-b0c7cdfa4ae7.Jpeg"/>
<content url="http://localhost:2023/FilesThumbs/aa1989f3-f4bd-489d-abca-b0c7cdfa4ae7.Jpeg"/>
</item>
But I Need file generate similar to this with rss tag and tag like Below is the xml file code and i need to create file similar to this
<?xml version="1.0" ?>
<rss version="2.0" xmlns:media="http://search.yahoo.com/mrss/" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<item>
<title>mastercard.png</title>
<media:description><a href=' http://localhost:2023/Files/054ee47b-7ecf-42d1-bfcc-06ac5f84b6d4.png'</media:description>
<link>http://localhost:2023/Files/054ee47b-7ecf-42d1-bfcc-06ac5f84b6d4.png</link>
<media:thumbnail url="http://localhost:2023/FilesThumbs/054ee47b-7ecf-42d1-bfcc-06ac5f84b6d4.Jpeg" />
<media:content url="http://localhost:2023/FilesThumbs/054ee47b-7ecf-42d1-bfcc-06ac5f84b6d4.Jpeg" />
</item>
</channel>
</rss>
hi please check updated code with some changes you will now get expect output
you just need to update value of tag and your output will be ready
XmlDocument writer = new XmlDocument();
// Create XML declaration
XmlNode declaration = writer.CreateNode(XmlNodeType.XmlDeclaration, null, null);
writer.AppendChild(declaration);
//add rss node over here
XmlElement rssElement = writer.CreateElement("rss");
rssElement.SetAttribute("version", "2.0");
rssElement.SetAttribute("xmlns:media", "http://search.yahoo.com/mrss/");
rssElement.SetAttribute("xmlns:atom", "http://www.w3.org/2005/Atom");
//Channel
XmlElement channelElement = writer.CreateElement("Channel");
XmlElement itemElement = writer.CreateElement("item");
//title
XmlElement titleElement = writer.CreateElement("title");
titleElement.InnerText = "mastercard.png";
itemElement.AppendChild(titleElement);
//media:description
XmlElement media_DescriptionElement = writer.CreateElement("media", "description", "media:description");
media_DescriptionElement.InnerText = "<a href=' http://localhost:2023/Files/054ee47b-7ecf-42d1-bfcc-06ac5f84b6d4.png";
itemElement.AppendChild(media_DescriptionElement);
//link
XmlElement linkElement = writer.CreateElement("link");
linkElement.InnerText = "http://localhost:2023/Files/aa1989f3-f4bd-489d-abca-b0c7cdfa4ae7.png";
itemElement.AppendChild(linkElement);
//media:thumbnail
XmlElement media_ThumbnailElement = writer.CreateElement("media", "thumbnail", "media:thumbnail");
media_ThumbnailElement.SetAttribute("url", "http://localhost:2023/FilesThumbs/054ee47b-7ecf-42d1-bfcc-06ac5f84b6d4.Jpeg");
itemElement.AppendChild(media_ThumbnailElement);
//media:content
XmlElement media_ContentElement = writer.CreateElement("media", "content", "media:content");
media_ContentElement.SetAttribute("url", "http://localhost:2023/FilesThumbs/054ee47b-7ecf-42d1-bfcc-06ac5f84b6d4.Jpeg");
itemElement.AppendChild(media_ContentElement);
channelElement.AppendChild(itemElement);
rssElement.AppendChild(channelElement);
writer.AppendChild(rssElement);
Output
<?xml version="1.0"?>
<rss version="2.0" xmlns:media="http://search.yahoo.com/mrss/" xmlns:atom="http://www.w3.org/2005/Atom">
<Channel>
<item>
<title>mastercard.png</title>
<media:description xmlns:media="media:description">&lt;a href=' http://localhost:2023/Files/054ee47b-7ecf-42d1-bfcc-06ac5f84b6d4.png</media:description>
<link>http://localhost:2023/Files/aa1989f3-f4bd-489d-abca-b0c7cdfa4ae7.png</link>
<media:thumbnail url="http://localhost:2023/FilesThumbs/054ee47b-7ecf-42d1-bfcc-06ac5f84b6d4.Jpeg" xmlns:media="media:thumbnail" />
<media:content url="http://localhost:2023/FilesThumbs/054ee47b-7ecf-42d1-bfcc-06ac5f84b6d4.Jpeg" xmlns:media="media:content" />
</item>
</Channel>
</rss>
Well, first and foremost, although it doesn't really change anything, it's important to realize that both XDocument and XElement accepts params, i.e. a list of items to add. This will make your code much more readable. For example:
var xdoc = new XDocument(
new XElement("root",
new XElement("foo"),
new XElement("bar")
);
);
That way the hierarchy is very clear, and you're not throwing variables all over the place.
Second, you literally made your root <channel>, rather than <rss>, so simply make <rss> your root element in your XDocument and then add <channel> to that, rather than directly to the XDocument as you're doing now.
Third, you can add attributes to elements using XAttribute. However, for namespaces, you want to persist these in a variable, so you can utilize them later as you're building your XML document. For example:
var media = XNamespace.Get("http://search.yahoo.com/mrss/");
var atom = XNamespace.Get("http://www.w3.org/2005/Atom");
var xdoc = new XDocument(
new XElement("rss",
new XAttribute("version", "2.0"),
new XAttribute(XNamespace.Xmlns + "media", media),
new XAttribute(XNamespace.Xmlns + "atom", atom),
new XElement("channel",
...
)
)
);
Then, when you need to use one of these namespaces, you concatentate it to the element name. For example, with media:thumbnail:
new XElement(media + "thumbnail",
new XAttribute("url", e_thumbnail)
)
Finally, if you use ToString on the XDocument, it will strip the XML declaration, for some boneheaded reason. Instead, you need to use a TextWriter to get the output:
var sb = new StringBuilder();
using (TextWriter writer = new Utf8StringWriter(sb))
{
xdoc.Save(writer);
}
var xmlString = sb.ToString();
FWIW, this is why you should name your XDocument variable something like xdoc rather than writer. For one, XDocument doesn't actually "write" anything, but also, writer is generally reserved for actual "writers" like TextWriter. That's all semantic, of course, but especially when dealing with XML, which usually involves voluminous amounts of code, you want it to be as readable and understandable as possible.
One last little tip. When building XML in the way I've shown here, you can pass actual enumerables just as well as single items. For example, let's say you created your list of channel items separately, such that you have a List<XElement> called items. You can actually just do:
new XElement("channel",
new XElement("title", "My Awesome Channel"),
new XElement("link", "https://foo.com/rss"),
new XElement("description", "Best channel ever!"),
items
)
EDIT
I completely forgot about Utf8StringWriter. That's a derived class of StringWriter, because StringWriter stupidly returns UTF16, and there's no way to modify that without deriving from it. The implementation is simple, but you'll need to add this to your project:
internal sealed class Utf8StringWriter : StringWriter
{
public Utf8StringWriter(StringBuilder sb)
: base(sb)
{
}
public override Encoding Encoding
{
get { return Encoding.UTF8; }
}
}
If you want to put this in a class library or something and share it between projects, just change internal to public.

How to add Namespace and Declaration in XDocument

I am creating xml in C#, and want to add Namespace and Declaration . My xml as below:
XNamespace ns = "http://ab.com//abc";
XDocument myXML = new XDocument(
new XDeclaration("1.0","utf-8","yes"),
new XElement(ns + "Root",
new XElement("abc","1")))
This will add xmlns="" at both Root level and child element abc level as well.
<Root xmlns="http://ab.com/ab">
<abc xmlns=""></abc>
</Root>
But I want it in only Root level not in child level like below:
<Root xmlns="http://ab.com/ab">
<abc></abc>
</Root>
and how to add Declaration at Top, my code not showing Declaration after run.
Please help me to get the complete xml as
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<Root xmlns="http://ab.com/ab">
<abc></abc>
</Root>
You need to use the same namespace in your child elements:
XDocument myXML = new XDocument(
new XDeclaration("1.0","utf-8","yes"),
new XElement(ns + "Root",
new XElement(ns + "abc", "1")))
If you just use "abc" this will be converted to an XName with no Namespace. This then results in an xmlns="" attribute being added so the fully qualified element name for abc would be resolved as such.
By setting the name to ns + "abc" no xmlns attribute will be added when converted to string as the default namespace of http://ab.com/ab is inherited from Root.
If you wanted to simply 'inherit' the namespace then you wouldn't be able to do this in such a fluent way. You'd have create the XName using the namespace of the parent element, for example:
var root = new XElement(ns + "Root");
root.Add(new XElement(root.Name.Namespace + "abc", "1"));
Regarding the declaration, XDocument doesn't include this when calling ToString. It will if you use Save to write to a Stream, TextWriter, or if you supply an XmlWriter that doesn't have OmitXmlDeclaration = true in its XmlWriterSettings.
If you wanted to just get the string, this question has an answer with a nifty extension method using a StringWriter.
Use the namespace on all elements you create:
XDocument myXML = new XDocument(
new XDeclaration("1.0","utf-8","yes"),
new XElement(ns + "Root",
new XElement(ns + "abc","1")))

ASP.net Creating an XLink node in and XDocument

I am trying to programmatically add a new XLink node to an XDocument but .Net seems to be creating them as atomized namespaces and names and I can't find any code to add XLink nodes to XML?
My code looks like this:
//read in the current XML content
XDocument content = XDocument.Parse(xmlContent);
//add a new node called large images
XElement newNode = new XElement("large_images", "");
newNode.SetAttributeValue("{xmlns}xlink", "http://www.w3.org/1999/xlink");
newNode.SetAttributeValue("{xlink}type", "simple");
newNode.SetAttributeValue("{xlink}href", "tcm:5-550");
newNode.SetAttributeValue("{xlink}title", "of1_454x340.jpg");
content.Add(newNode);
Unfortunately this newNode comes out like this:
<large_images p1:xlink="http://www.w3.org/1999/xlink" p2:type="simple" p2:href="tcm:5-550" p2:title="of1_454x340.jpg" xmlns:p2="xlink" xmlns:p1="xmlns"></large_images>
But I need the node to look like this in order for it to pass the XML validation:
<large_images xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="tcm:5-550" xlink:title="of1_454x340.jpg"></large_images>
Can anybody help? I don't want to go down the String.Replace() route as it seems that this must be possible another way?
Thanks
Ryan
I'd do that as:
XNamespace ns = "http://www.w3.org/1999/xlink";
XElement newNode = new XElement("large_images",
new XAttribute(XNamespace.Xmlns + "xlink", ns),
new XAttribute(ns + "type", "simple),
new XAttribute(ns + "href", "tcm:5-550"),
new XAttribute(ns + "title", "of1_454x340.jpg"));
This produces XML of:
<large_images xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple"
xlink:href="tcm:5-550" xlink:title="of1_454x340.jpg" />

Categories