C# 将 XML 字符串注入 XmlWriter 时的 XML 缩进
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/858630/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
XML indenting when injecting an XML string into an XmlWriter
提问by Colin Burnett
I have an XmlTextWriter writing to a file and an XmlWriter using that text writer. This text writer is set to output tab-indented XML:
我有一个写入文件的 XmlTextWriter 和一个使用该文本编写器的 XmlWriter。此文本编写器设置为输出制表符缩进的 XML:
XmlTextWriter xtw = new XmlTextWriter("foo.xml", Encoding.UTF8);
xtw.Formatting = Formatting.Indented;
xtw.IndentChar = '\t';
xtw.Indentation = 1;
XmlWriter xw = XmlWriter.Create(xtw);
Changed per Jeff's MSDN link:
根据 Jeff 的 MSDN 链接更改:
XmlWriterSettings set = new XmlWriterSettings();
set.Indent = true;
set.IndentChars = "\t";
set.Encoding = Encoding.UTF8;
xw = XmlWriter.Create(f, set);
This does not change the end result.
这不会改变最终结果。
Now I'm an arbitrary depth in my XmlWriter and I'm getting a string of XML from elsewhere (that I cannot control) that is a single-line, non-indented XML. If I call xw.WriteRaw() then that string is injected verbatim and does not follow my indentation I want.
现在我是 XmlWriter 中的任意深度,并且我从其他地方(我无法控制)获取一串 XML,它是一个单行、非缩进的 XML。如果我调用 xw.WriteRaw() ,那么该字符串将逐字注入并且不遵循我想要的缩进。
...
string xml = ExternalMethod();
xw.WriteRaw(xml);
...
Essentially, I want a WriteRaw that will parse the XML string and go through all the WriteStartElement, etc. so that it gets reformatted per the XmlTextWriter's settings.
本质上,我想要一个 WriteRaw 来解析 XML 字符串并遍历所有 WriteStartElement 等,以便根据 XmlTextWriter 的设置对其进行重新格式化。
My preference is a way to do this with the setup I already have and to do this without having to reload the final XML just to reformat it. I'd also prefer not to parse the XML string with the likes of XmlReader and then mimic what it finds into my XmlWriter (very very manual process).
我的偏好是使用我已有的设置来执行此操作,并且无需重新加载最终的 XML 来重新格式化它。我也不想用 XmlReader 之类的东西解析 XML 字符串,然后模仿它在我的 XmlWriter 中找到的内容(非常非常手动的过程)。
At the end of this I'd rather have a simple solution than one that follows my preferences. (Best solution, naturally, would be simple and follows my preferences.)
最后,我宁愿有一个简单的解决方案,也不愿遵循我的喜好。(当然,最好的解决方案应该很简单,并遵循我的喜好。)
采纳答案by aaronb
How about using a XmlReader to read the xml as xml nodes?
如何使用 XmlReader 将 xml 读取为 xml 节点?
string xml = ExternalMethod();
XmlReader reader = XmlReader.Create(new StringReader(xml));
xw.WriteNode(reader, true);
回答by Jeff Yates
You shouldn't use XmlTextWriter
, as indicated in MSDN where it states:
您不应该使用XmlTextWriter
,如 MSDN 中指出的那样:
In the .NET Framework version 2.0 release, the recommended practice is to create XmlWriter instances using the XmlWriter.Create method and the XmlWriterSettings class. This allows you to take full advantage of all the new features introduced in this release. For more information, see Creating XML Writers.
在 .NET Framework 2.0 版中,推荐的做法是使用 XmlWriter.Create 方法和 XmlWriterSettings 类创建 XmlWriter 实例。这使您可以充分利用此版本中引入的所有新功能。有关更多信息,请参阅创建 XML 编写器。
Instead, you should use XmlWriter.Createto get your writer. You can then use the XmlWriterSettings
class to specify things like indentation.
相反,您应该使用XmlWriter.Create来获取您的编写器。然后,您可以使用XmlWriterSettings
该类来指定诸如缩进之类的内容。
XmlWriterSettings settings = new XmlWriterSettings();
settings.Indent = true;
settings.IndentChars = "\t";
Update
更新
I think you can just use WriteNode. You take your xml string and load it into an XDocument or XmlReader and then use the node from that to write it into your XmlWriter.
我认为你可以只使用 WriteNode。您将 xml 字符串加载到 XDocument 或 XmlReader 中,然后使用其中的节点将其写入 XmlWriter。
回答by Colin Burnett
This is the best I've got so far. A very manual process that only supports what is written. My string XML is nothing more than tags, attributes, and text data. If it supported namespaces, CDATA, etc. then this would have to grow accordingly.
这是我迄今为止最好的。一个非常手动的过程,只支持所写的内容。我的字符串 XML 只不过是标签、属性和文本数据。如果它支持命名空间、CDATA 等,那么它必须相应地增长。
Very manual, very messy and very likely prone to bugs but it does accomplish my preferences.
非常手动,非常凌乱,很可能容易出现错误,但它确实满足了我的喜好。
private static void PipeXMLIntoWriter(XmlWriter xw, string xml)
{
byte[] dat = new System.Text.UTF8Encoding().GetBytes(xml);
MemoryStream m = new MemoryStream();
m.Write(dat, 0, dat.Length);
m.Seek(0, SeekOrigin.Begin);
XmlReader r = XmlReader.Create(m);
while (r.Read())
{
switch (r.NodeType)
{
case XmlNodeType.Element:
xw.WriteStartElement(r.Name);
if (r.HasAttributes)
{
for (int i = 0; i < r.AttributeCount; i++)
{
r.MoveToAttribute(i);
xw.WriteAttributeString(r.Name, r.Value);
}
}
if (r.IsEmptyElement)
{
xw.WriteEndElement();
}
break;
case XmlNodeType.EndElement:
xw.WriteEndElement();
break;
case XmlNodeType.Text:
xw.WriteString(r.Value);
break;
default:
throw new Exception("Unrecognized node type: " + r.NodeType);
}
}
}
回答by zam6ak
How about:
怎么样:
string xml = ExternalMethod();
var xd = XDocument.Parse(xml);
xd.WriteTo(xw);
回答by GreyCloud
composing the answers above I have found this works:
组成上面的答案我发现这有效:
private static string FormatXML(string unformattedXml) {
// first read the xml ignoring whitespace
XmlReaderSettings readeroptions= new XmlReaderSettings {IgnoreWhitespace = true};
XmlReader reader = XmlReader.Create(new StringReader(unformattedXml),readeroptions);
// then write it out with indentation
StringBuilder sb = new StringBuilder();
XmlWriterSettings xmlSettingsWithIndentation = new XmlWriterSettings { Indent = true};
using (XmlWriter writer = XmlWriter.Create(sb, xmlSettingsWithIndentation)) {
writer.WriteNode(reader, true);
}
return sb.ToString();
}
回答by landete85
I was looking for an answer to this issue but in VB.net.
我正在寻找这个问题的答案,但在 VB.net 中。
Thanks to Colin Burnett, I solved it. I made two corrections: first, the XmlReader
has to ignore white spaces (settings.IgnoreWhiteSpaces
); second, the reader has to be back into the element after it reads attributes. Below you can see how the code looks like.
感谢 Colin Burnett,我解决了它。我做了两个更正:首先,XmlReader
必须忽略空格 ( settings.IgnoreWhiteSpaces
);其次,读取器在读取属性后必须回到元素中。您可以在下面看到代码的样子。
Also I tried the solution of GreyCloud, but in the generated XML there were some annoying empties attributes (xlmns).
我也尝试了 GreyCloud 的解决方案,但在生成的 XML 中有一些烦人的空属性 (xlmns)。
Private Sub PipeXMLIntoWriter(xw As XmlWriter, xml As String)
Dim dat As Byte() = New System.Text.UTF8Encoding().GetBytes(xml)
Dim m As New MemoryStream()
m.Write(dat, 0, dat.Length)
m.Seek(0, SeekOrigin.Begin)
Dim settings As New XmlReaderSettings
settings.IgnoreWhitespace = True
settings.IgnoreComments = True
Dim r As XmlReader = XmlReader.Create(m, settings)
While r.Read()
Select Case r.NodeType
Case XmlNodeType.Element
xw.WriteStartElement(r.Name)
If r.HasAttributes Then
For i As Integer = 0 To r.AttributeCount - 1
r.MoveToAttribute(i)
xw.WriteAttributeString(r.Name, r.Value)
Next
r.MoveToElement()
End If
If r.IsEmptyElement Then
xw.WriteEndElement()
End If
Exit Select
Case XmlNodeType.EndElement
xw.WriteEndElement()
Exit Select
Case XmlNodeType.Text
xw.WriteString(r.Value)
Exit Select
Case Else
Throw New Exception("Unrecognized node type: " + r.NodeType)
End Select
End While
End Sub