我正在尝试构建XML文档的一小部分,以包含在最终文档中。
使用XDocument
时,我得到一个例外:
“此操作会创建一个结构不正确的文档。”
因为我的片段有多个“根”节点。
由于文件要包含在较大的文档中,因此我的基本元素不会以最终文档的根目录结束。
XDocument constsDocument = new XDocument(
new XComment($" Consts section generated on {DateTime.Now} "),
new XComment($" First group of constants. "),
FirstTextConsts(MyFirstCollection),
new XComment($" Refrigerant constants. "),
SecondTextConsts(MySecondCollection)
);
// To avoid xml file starting with <?xml version="1.0" encoding="utf-8"?> use stringbuilder and StreamWriter.
StringBuilder sb = new StringBuilder();
XmlWriterSettings xws = new XmlWriterSettings
{
OmitXmlDeclaration = true,
Indent = true
};
using (XmlWriter xw = XmlWriter.Create(sb, xws))
{
constsDocument.Save(xw);
}
System.IO.StreamWriter file = new System.IO.StreamWriter(_outputFileName);
file.WriteLine(sb.ToString());
file.Close();
编辑1: 在文档创建中调用的两种方法(原则上):
private static IEnumerable<XElement> FirstTextConsts(IEnumerable<MyClass> collection)
{
return collection.Select(r => new XElement("const",
new XAttribute("name", $"IDENTIFIER_{r.Id}"),
new XAttribute("translatable", "false"),
new XElement("text",
new XAttribute("lang","en"), r.Name)));
}
private static IEnumerable<XElement> SecondTextConsts(IEnumerable<MyClass> collection)
{
foreach (var obj in collection)
{
if (obj.SomeSelector)
yield return new XElement("const",
new XAttribute("name", $"IDENTIFIER_{r.Id}"),
new XAttribute("translatable", "false"),
new XElement("text",
new XAttribute("lang","en"), r.Name)));
if (obj.SomeOtherSelector)
yield return new XElement("const",
new XAttribute("name", $"IDENTIFIER_{r.Id}"),
new XAttribute("translatable", "true")
);
}
}
编辑2: 因为我真的需要XDocument的灵活性来构建一个多级xml文档机智助手方法在不同级别上返回IEnumerable,所以我决定添加一个假元素并在写入文件之前将其删除:
XDocument constsDocument = new XDocument(
new XElement("root",
new XComment($" Consts section generated on {DateTime.Now} "),
new XComment($" First group of constants. "),
FirstTextConsts(MyFirstCollection),
new XComment($" Refrigerant constants. "),
SecondTextConsts(MySecondCollection)
)
);
在写入文件之前,我删除了元素:
file.WriteLine(sb.ToString().Replace("<root>" + Environment.NewLine, "").Replace(Environment.NewLine + "</root>", ""));
答案 0 :(得分:3)
您无法创建无效的XDocument
(由于多个“根”节点)。因此,您需要创建节点列表,并将其写入文档片段。
var constsDocument = new List<XNode> {
new XComment($" Consts section generated on {DateTime.Now} "),
new XComment($" First group of constants. "),
new XElement("example"),
new XComment($" Refrigerant constants. "),
new XElement("another")
};
// To avoid xml file starting with <?xml version="1.0" encoding="utf-8"?> use stringbuilder and StreamWriter.
StringBuilder sb = new StringBuilder();
XmlWriterSettings xws = new XmlWriterSettings
{
OmitXmlDeclaration = true,
Indent = true,
ConformanceLevel = ConformanceLevel.Fragment
};
using (XmlWriter xw = XmlWriter.Create(sb, xws))
{
foreach (var element in constsDocument)
{
element.WriteTo(xw);
}
}
System.IO.StreamWriter file = new System.IO.StreamWriter(_outputPath);
file.WriteLine(sb.ToString());
file.Close();
编辑:要使用在IEnumerable<XElement>
的对象初始值设定项中返回List
的方法,您必须稍微更改定义以及添加其他项的方式:
var constsDocument = new List<IEnumerable<XNode>> {
new [] { new XComment($" Consts section generated on {DateTime.Now} ") },
new [] { new XComment($" First group of constants. ") },
FirstTextConsts(MyFirstCollection),
new [] { new XComment($" Refrigerant constants. ") },
SecondTextConsts(MySecondCollection)
);
...
foreach (var element in constsDocument.SelectMany(n => n))
答案 1 :(得分:1)
您可以声明您希望XML只是一个片段并从XDocument切换到XMLDocument:
XmlDocument constDocument = new XmlDocument();
constDocument.CreateComment(" Consts section generated on {DateTime.Now} ");
constDocument.CreateComment(" First group of constants. ");
FirstTextConsts(MyFirstCollection); // Need to be adapted
constDocument.CreateComment(" Refrigerant constants. ");
SecondTextConsts(MySecondCollection); // Need to be adapted
XmlDocumentFragment fragDocument = constDocument.CreateDocumentFragment();
fragDocument.InnerXml = "<const>fragment</const><const>fragment2</const>"; // Need to be adapted
StringBuilder sb = new StringBuilder();
XmlWriterSettings xws = new XmlWriterSettings
{
ConformanceLevel = ConformanceLevel.Fragment,
OmitXmlDeclaration = true,
Indent = true
};
using (XmlWriter xw = XmlWriter.Create(sb, xws))
{
fragDocument.WriteContentTo(xw);
}
System.IO.StreamWriter file = new System.IO.StreamWriter(_outputFileName);
file.WriteLine(sb.ToString());
file.Close();
或添加aritificial root元素:
"<aritificialroot>" + fragment + "</aritificialroot>"