我正在将XML消息发送到无法处理标记中的空格的系统。值中的空格可以。我一直在使用linq / XDocument / XElements来操纵/生成消息。
问题在于元素为空。例如:
XDocument xdoc = XDocument.Parse("<root><value/></root>");
Console.WriteLine(xdoc.ToString(SaveOptions.DisableFormatting));
即使打开DisableFormatting
,它也会在元素标题后的标记中输出带有空格的字符串。
<root><value /></root>
所以我只是在上面放了一个替换:
Console.WriteLine(xdoc.ToString(SaveOptions.DisableFormatting).Replace(" />","/>"));
有什么坏事我可以碰到那里吗?有明显/更标准的方法可以做到这一点吗?好像很烂。
答案 0 :(得分:1)
如果目标系统对待空xml元素的方式与自动关闭xml元素的方式相同-通常,两者都被认为是相等的(但请考虑此post上的说明)-您可以实现自定义XmlWriter
,该自定义<value></value>
会将自关闭xml标签输出为空xml标签。
空的xml标签在其标签内将不包含任何空格,例如。 XmlTextWriter
。
下面的示例中的自定义<value></value>
产生以下xml。
请注意valueWithWhitespace
标签,并且<root><value></value><valueWithWhitespace> </valueWithWhitespace></root>
的空白值已保留。
var xml = XElement.Parse(
"<root><value /><valueWithWhitespace> </valueWithWhitespace></root>",
LoadOptions.PreserveWhitespace
);
var stringWriter = new StringWriter();
using (var xmlWriter = new CustomXmlTextWriter(stringWriter))
{
xml.WriteTo(xmlWriter);
xmlWriter.Flush();
Console.WriteLine(stringWriter);
}
public class CustomXmlTextWriter : XmlTextWriter
{
public CustomXmlTextWriter(TextWriter writer)
: base(writer)
{}
public CustomXmlTextWriter(Stream stream, Encoding encoding)
: base(stream, encoding)
{}
public CustomXmlTextWriter(string filename, Encoding encoding)
: base(filename, encoding)
{}
public override void WriteEndElement()
{
this.WriteFullEndElement();
}
}
"reviewers": [
{
"uuid": "{504c3b62-8120-4f0c-a7bc-87800b9d6f70}"
},
{
"uuid": "{bafabef7-b740-4ee0-9767-658b3253ecc0}"
}
]
答案 1 :(得分:0)
如果您可以使用额外的缓冲(使用String.Replace,看起来还可以),也可以用其他方式完成:
class CustomXmlTextWriter : XmlTextWriter {
public CustomXmlTextWriter(MemoryStream stream) : base(stream, new UTF8Encoding(false)) { }
public override void WriteEndElement() {
base.WriteEndElement();
base.Flush();
var stream = (MemoryStream)BaseStream;
var buffer = stream.GetBuffer();
var pos = stream.Position;
if (pos > 3 && buffer[pos - 1] == '>' && buffer[pos - 2] == '/' && buffer[pos - 3] == ' ') {
stream.Seek(-3, SeekOrigin.Current);
stream.WriteByte((byte)'/');
stream.WriteByte((byte)'>');
}
}
}
然后您可以将其从内存流中取出。与字符串替换的区别在于,这种方法不会破坏CDATA部分之类的东西。使用完全结束标记的不同之处在于,它可能会更紧密地复制您已解析的内容。