XmlWriter.Create返回特定XmlRawWriter包裹在XmlWellFormedWriter,所有这些被定义为内部所以不能扩展它们。
但是,您可以扩展XmlTextWriter的,但相对于中规中矩的作家它有一个非常有限的功能集。
所以......
这是我作出处理这个问题上,有多数的功能从井中形成的作家失踪,节选XmlWriterSettings自定义的XmlTextWriter:
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
namespace System.Xml
{
public class CustomXmlTextWriter : XmlTextWriter
{
internal class CustomStreamWriter : StreamWriter
{
public CustomStreamWriter(Stream stream, Encoding encoding) : base(stream) { }
// This prevents the XmlTextWriter from writing the extra space before attributes, and the short EndElement " />"
public bool DisableSpace { get; set; }
public override void Write(char value)
{
if (DisableSpace && value == ' ') return;
else base.Write(value);
}
public override void Write(string value)
{
if (DisableSpace && value == " /") base.Write('/');
else base.Write(value);
}
}
public CustomXmlTextWriter(string filename, XmlWriterSettings settings) : this(new FileStream(filename, FileMode.Create, FileAccess.Write, FileShare.Read), settings) { }
public CustomXmlTextWriter(Stream stream, XmlWriterSettings settings) : this(new CustomStreamWriter(stream, settings.Encoding), settings) { }
internal CustomXmlTextWriter(CustomStreamWriter writer, XmlWriterSettings settings)
: base(writer)
{
m_Writer = writer;
m_Settings = settings;
if (m_Settings.OmitXmlDeclaration == false)
{
string encoding = (m_Writer.Encoding.CodePage == 1201) ? "UTF-16BE" : m_Writer.Encoding.WebName;
m_Writer.WriteLine("<?xml version=\"1.0\" encoding=\"{0}\"?>", encoding);
}
}
private bool m_HasAttributes = false;
private Stack<bool> m_HasAttributesStack = new Stack<bool>();
private CustomStreamWriter m_Writer;
private XmlWriterSettings m_Settings;
public override XmlWriterSettings Settings { get { return m_Settings; } }
public override void WriteStartElement(string prefix, string localName, string ns)
{
if (WriteState == WriteState.Element)
{
if (m_HasAttributes && Settings.NewLineOnAttributes) { WriteIndent(m_HasAttributesStack.Count); }
WriteRaw(""); // Trick the XmlTextWriter into closing the previous element, and updating the WriteState
m_Writer.DisableSpace = false;
}
int indentLevel = m_HasAttributesStack.Count;
if (indentLevel > 0)
{
WriteIndent(indentLevel);
}
m_HasAttributesStack.Push(m_HasAttributes);
m_HasAttributes = false;
base.WriteStartElement(prefix, localName, ns);
}
public override void WriteEndElement()
{
if (m_HasAttributes && Settings.NewLineOnAttributes)
{
WriteIndent(m_HasAttributesStack.Count - 1);
}
m_HasAttributes = m_HasAttributesStack.Pop();
base.WriteEndElement();
m_Writer.DisableSpace = false;
}
public override void WriteFullEndElement()
{
m_HasAttributes = m_HasAttributesStack.Pop();
WriteIndent(m_HasAttributesStack.Count);
base.WriteFullEndElement();
}
public override void WriteStartAttribute(string prefix, string localName, string ns)
{
if (Settings.NewLineOnAttributes)
{
WriteIndent(m_HasAttributesStack.Count);
m_Writer.DisableSpace = true;
}
m_HasAttributes = true;
base.WriteStartAttribute(prefix, localName, ns);
}
public override void WriteString(string text)
{
if (m_Settings.NewLineHandling == NewLineHandling.Replace)
{
text = Regex.Replace(text, @"\r\n?|\n", m_Settings.NewLineChars);
}
else if (m_Settings.NewLineHandling == NewLineHandling.Entitize)
{
text = Regex.Replace(text, @"\n|\r", m => String.Format("&#x{0:X};", (int)m.Value[0]));
}
base.WriteString(text);
}
private void WriteIndent(int indentLevel)
{
if (Settings.Indent == false) return;
m_Writer.Write(Settings.NewLineChars);
for (int i = 0; i < indentLevel; ++i)
{
m_Writer.Write(Settings.IndentChars);
}
}
}
}
刚使含在你的项目上面的代码的文件,然后使用它像这样:
// Create the XmlWriter Settings as you normally would
// *Note: You can change or omit these, they are just for an example of what I supported
XmlWriterSettings settings = new XmlWriterSettings()
{
Encoding = Encoding.UTF8,
//OmitXmlDeclaration = true,
Indent = true,
//IndentChars = " ",
IndentChars = "\t",
NewLineOnAttributes = true,
//NewLineHandling = NewLineHandling.Entitize,
//NewLineHandling = NewLineHandling.Replace,
//NewLineChars = @"\n",
};
// Replace XmlWriter.Create with new CustomXmlTextWriter
//using (XmlWriter writer = XmlWriter.Create(path, settings))
using (XmlWriter writer = new CustomXmlTextWriter(path, settings))
{
xml.WriteTo(writer);
}
这将是很好,如果这个功能刚刚加入到孔中形成的WR iter作为XmlWriterSettings中的一个选项。
有时更改diff工具不是一个选项(或者甚至是第一个问题) 当使用像perforce这样的系统通过工具自动合并更改时,最好尽可能保持更改原子。
例如... 如果最后一个属性被一个人改变,并且另一个人被添加到另一个属性的末尾,没有理由根据哪一行应该包含关闭来创建人为冲突>(或/>)。 对于这种情况,最好的解决方案是如果右括号是在自己的行上,并且避免所有的冲突。
你能更具体?当从'继承XmlWriter'我甚至不看如何构建我的'base'(带内置的执行我使用静态'.Create'方法,但我怎么通过这个我'base'工作时?)。 – Motti 2009-08-23 14:48:42
XmlWriter构造函数受保护,因此您可以从派生类中调用它。然而,它会更容易直接从XmlTextWriter的继承,这样你就不必编写一切从头开始 – 2009-08-23 14:56:53
我给它一个尝试,它似乎并不可能做到,如果没有大量的代码......反正,如果你唯一的格式问题是差异工具,我建议你使用一种理解XML的工具,并比较语义,而不仅仅是文本。如果您使用Beyond Compare,则在比较它们之前,会有一个插件用Tidy格式化这两个文档。 – 2009-08-23 15:55:51