如何强制使用Linq XML显式标记关闭?
这是相同的问题: Explicit Element Closing Tags with System.Xml.Linq Namespace如何强制使用Linq XML显式标记关闭?
但我使用Net 4.0和答案不再工作。
问题是我保存的标签,没有价值真的,我的输出XML是这样的:
<field/>
但我需要的是始终在打开和关闭标签,即
<field></field>
问题:怎么办?
编辑
添加空节点:
if (field_xml == null) // always true, because I create the file for the first time
{
field_xml = new XElement(XMLKeys.field,String.Empty);
table_xml.Add(field_xml);
}
field_xml.SetAttributeValue(XMLKeys.name, field_info.Name);
// ... setting some other attributes of this node
后来,保存XML:
var writer = new FullEndingXmlTextWriter(parameters.OutputFilename, Encoding.UTF8);
root_xml.Save(writer);
FullEndingXmlTextWriter是专业类的邪恶Greebo指出(它应该强制显式结束标记)。
我无法重现您的错误。这将按预期在这两个4.0和3.5 NETFX:
namespace ExplicitXmlClosingTags
{
using System.Xml;
using System.Xml.Linq;
class Program
{
static void Main(string[] args)
{
const string ElementRoot = "RootElement";
const string ElementChild = "ChildElement";
const string AttributeChild = "ChildAttribute";
XDocument xDoc = new XDocument();
XElement root = new XElement(ElementRoot);
XElement child = new XElement(ElementChild, string.Empty);
root.Add(child);
child.SetAttributeValue(AttributeChild, "AttrValue");
xDoc.Add(root);
XmlWriterSettings xws = new XmlWriterSettings();
xws.Indent = true;
using (XmlWriter xw = XmlWriter.Create("out.xml", xws))
{
xDoc.Save(xw);
}
}
}
}
产生以下内容:
<?xml version="1.0" encoding="utf-8"?>
<RootElement>
<ChildElement ChildAttribute="AttrValue"></ChildElement>
</RootElement>
(谢谢你的答案)。现在,这**很有趣。我复制和粘贴你的例子,我做**不**具有明确的结束标签(我也试过。净3.5)。 Geee,兼容性... – greenoldman 2011-06-17 06:02:04
设定的值XElement
到String.Empty
OR
设置IsEmpty
属性false
不具有任何的子节点
foreach (XElement childElement in
from x in document.DescendantNodes().OfType<XElement>()
where x.IsEmpty
select x)
{
childElement.IsEmpty = false;
}
我做过了,这是上一篇文章的答案,但它不起作用。 – greenoldman 2011-06-15 08:57:18
编辑答案以显示另一种方法,将“IsEmpty”设置为“false”。 – harryovers 2011-06-15 09:35:09
你编译了这段代码吗?因为在这里我得到了错误信息,所以IsEmpty是只读属性。好奇你是怎样使它:-) – greenoldman 2011-06-16 05:38:22
的XElement
值明确设置为空的所有元素字符串应该工作。正如您从XElement.IsEmpty
的文档中看到的,LINQ到XML已经将节点没有内容(如new XElement("foo")
)视为与长度为零的节点(如new XElement("foo", string.Empty)
)不同。
但在不工作的情况下,或者如果你需要微调XML输出的一些其他方面,你可以得到一个定制XmlWriter
:
public class MyWriter : XmlWriter
{
private readonly XmlWriter inner;
public MyWriter(XmlWriter inner)
{
this.inner = inner;
}
public void Dispose()
{
((IDisposable) inner).Dispose();
}
public override void WriteStartDocument()
{
inner.WriteStartDocument();
}
public override void WriteStartDocument(bool standalone)
{
inner.WriteStartDocument(standalone);
}
public override void WriteEndDocument()
{
inner.WriteEndDocument();
}
public override void WriteDocType(string name, string pubid, string sysid, string subset)
{
inner.WriteDocType(name, pubid, sysid, subset);
}
public override void WriteStartElement(string prefix, string localName, string ns)
{
inner.WriteStartElement(prefix, localName, ns);
}
public override void WriteEndElement()
{
inner.WriteFullEndElement();
}
public override void WriteFullEndElement()
{
inner.WriteFullEndElement();
}
public override void WriteStartAttribute(string prefix, string localName, string ns)
{
inner.WriteStartAttribute(prefix, localName, ns);
}
public override void WriteEndAttribute()
{
inner.WriteEndAttribute();
}
public override void WriteCData(string text)
{
inner.WriteCData(text);
}
public override void WriteComment(string text)
{
inner.WriteComment(text);
}
public override void WriteProcessingInstruction(string name, string text)
{
inner.WriteProcessingInstruction(name, text);
}
public override void WriteEntityRef(string name)
{
inner.WriteEntityRef(name);
}
public override void WriteCharEntity(char ch)
{
inner.WriteCharEntity(ch);
}
public override void WriteWhitespace(string ws)
{
inner.WriteWhitespace(ws);
}
public override void WriteString(string text)
{
inner.WriteString(text);
}
public override void WriteSurrogateCharEntity(char lowChar, char highChar)
{
inner.WriteSurrogateCharEntity(lowChar, highChar);
}
public override void WriteChars(char[] buffer, int index, int count)
{
inner.WriteChars(buffer, index, count);
}
public override void WriteRaw(char[] buffer, int index, int count)
{
inner.WriteRaw(buffer, index, count);
}
public override void WriteRaw(string data)
{
inner.WriteRaw(data);
}
public override void WriteBase64(byte[] buffer, int index, int count)
{
inner.WriteBase64(buffer, index, count);
}
public override void Close()
{
inner.Close();
}
public override void Flush()
{
inner.Flush();
}
public override string LookupPrefix(string ns)
{
return inner.LookupPrefix(ns);
}
public override WriteState WriteState
{
get { return inner.WriteState; }
}
}
相关的方法是这样的一种:
public override void WriteEndElement()
{
inner.WriteFullEndElement(); // always write both start and close tags
}
类似的例子在这里谈论:http://stackoverflow.com/questions/1849214/render-empty-xml-elements-as-parent-elements我有同样的问题 - 我有一个黑盒子应用程序,需要完整的形成的XML和使用修改后的XmlWriter工作得非常好,以确保永远不会发送签约空标签。 – 2011-06-15 09:57:32
谢谢你的想法(顺便说一句你的代码是正确写入 - 在你继承和撰写的XmlWriter的同时,其实你应该继承,只覆盖构造函数和相关方法),但是...我一些倒霉的家伙,它仍然无法按预期工作。我在原始帖子中添加了一个编辑。 – greenoldman 2011-06-16 06:23:14
@macias:继承+构成是故意的。我写的MyWriter是一个[装饰器](http://en.wikipedia.org/wiki/Decorator_pattern)。它适用于任何XmlWriter,而不仅仅是XmlTextWriter。我完全按照原样对它进行了测试,并且工作正常。我编写了一个现有的XmlWriter实现,并继承了相同的接口。 – 2011-06-16 09:12:20
var document = XDocument.Parse(XMLData);
foreach (XElement childElement in
from x in document.DescendantNodes().OfType<XElement>()
where x.IsEmpty
select x)
{
childElement.Value = "";
}
试试这个工作。只需将childElement.IsEmpty = false;
替换为childElement.Value = ""
;
为什么这很重要? – 2011-06-15 08:51:25
@Dan软件“吃”这可能是小错误,并没有正确处理这个语法,我也一直处于这种情况。一般来说,这不重要。 – 2011-06-15 09:40:22