C#创建带有命名空间的XML文档

时间:2022-09-08 09:12:33

废话不多说,也不要问我为什么要加命名空间,能搜索到这里,必然也是需要增加命名空间。

我属于野路子,并没有仔细的了解过XML或是System.Xml和System.Xml.Linq相关内容,项目需要就抓来用,遇到这个问题被绊住了,网上也没有相关的答案,可能大家都会吧。那么既然网上没有,通过提问也得到了答案,就在这分享一下。


创建XML文档,可以使用DOM方式,也可以使用Linq to xml方式。


先贴出我要创建的xml文档内容,以便对比,这是一个svg格式的xml文件。

<?xml version="1.0" encoding="utf-8" standalone="no"?>
<svg width="770" height="485" viewBox="0 0 770 485" preserveAspectRatio="xMidYMid" xmlns="http://www.w3.org/2000/svg">
<line x1="20" y1="20" x2="100" y2="100" style="stroke:rgb(100,155,200);stroke-width:2" />
</svg>

根节点是:svg,包含一个xmlns属性。

最初,很自然的认为这个xmlns是一个属性,和其他属性一样添加就可以了。代码如下:

XDocument document = new XDocument(new XDeclaration("1.0", "UTF-8", "no"));
XNamespace ns = "http://www.w3.org/2000/svg";
XElement root = new XElement(ns + "svg");
root.Add(
new XAttribute("width", this.Size.Width)
, new XAttribute("height", this.Size.Height)
, new XAttribute("viewBox", "0 0 " + this.Size.Width.ToString() + " " + this.Size.Height.ToString())
, new XAttribute("xmlns", "http://www.w3.org/2000/svg")
, new XAttribute("preserveAspectRatio", "xMidYMid"));
document.Add(root);
MemoryStream stream = new MemoryStream();
XmlWriter writer = XmlWriter.Create(stream);
document.WriteTo(writer);
writer.Close();
return Encoding.UTF8.GetString(stream.GetBuffer());

编译正确,运行时会提示一个异常信息:

在同一开始元素标记中,无法将前缀“”从“”重定义为“http://www.w3.org/2000/svg”。

在我发帖

http://bbs.csdn.net/topics/390937832

得到了不少解决方法,都可以设置命名空间。

XDocument document = new XDocument(new XDeclaration("1.0", "UTF-8", "no"));
XNamespace ns = "http://www.w3.org/2000/svg";
XElement root = new XElement(ns + "svg");
root.Add(
new XAttribute("width", this.Size.Width)
, new XAttribute("height", this.Size.Height)
, new XAttribute("viewBox", "0 0 " + this.Size.Width.ToString() + " " + this.Size.Height.ToString())
, new XAttribute("preserveAspectRatio", "xMidYMid"));
document.Add(root);
MemoryStream stream = new MemoryStream();
XmlWriter writer = XmlWriter.Create(stream);
document.WriteTo(writer);
writer.Close();
return Encoding.UTF8.GetString(stream.GetBuffer());

这个是最符合我需求的。

关键区别就是名字需要先声明XNamespace,并在创建XElement的时候,附在前面。

如果只是这样写,添加的子节点依然会多一个无用的属性:xmlns=""

不删除会出错。

所以,如果要添加子节点,也需要和根节点一样添加XNamespace在XElement名字前面。


下面是用DOM方式创建svg文件。

Func<XmlDocument, string, string, XmlAttribute> CreateXmlAttribute = (document, name, value) =>
{
XmlAttribute attribute = document.CreateAttribute(name);
attribute.Value = value;
return attribute;
};

XmlDocument doc = new XmlDocument();
XmlDeclaration declaration = doc.CreateXmlDeclaration("1.0", "UTF-8", "no");
doc.AppendChild(declaration);
XmlElement root = doc.CreateElement("svg");
root.Attributes.Append(CreateXmlAttribute(doc, "width", this.Size.Width.ToString()));
root.Attributes.Append(CreateXmlAttribute(doc, "height", this.Size.Height.ToString()));
root.Attributes.Append(CreateXmlAttribute(doc, "viewBox", "0 0 " + this.Size.Width.ToString() + " " + this.Size.Height.ToString()));
root.Attributes.Append(CreateXmlAttribute(doc, "xmlns", "http://www.w3.org/2000/svg"));
root.Attributes.Append(CreateXmlAttribute(doc, "preserveAspectRatio", "xMidYMid"));
doc.AppendChild(root);
if (this.Count > 0) this.Values.ToList().ForEach(d => root.AppendChild(d.GetSvgElement(doc)));
return doc.InnerXml;


这里我也只能说个技巧,原理不懂,如果写
root.Attributes.Append(new XmlAttribute("xmlns","http://www.w3.org/2000/svg"));

这样就会异常,但分开写,通过设置value赋值就不会有错。


项目紧急,我本只想做自己收录,但担心哪天还用的上,不好找。就发博客吧。
稍后有空,我会仔细了解XML,DOM和LinqToXml相关内容,希望能从原理上了解这个乌龙问题。
在了解的人面前班门弄斧了,但如果有人和我一样遇到问题,看看这个文章可以迅速解决问题,这才是本文的意义。
感谢Tim和“人”两位好友的帮助。