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