2011-01-05 99 views
3

目前我正在使用XML存儲許多數據,並且在創建這些XML文件時,我想將其大小降至最小。刪除結束元素的空間?

我怎麼能覆蓋的XmlWriter功能(對writeEndElement),因此而不是保存它喜歡:

<thisElement someAttribute="blabla" /> 

它將被保存,如:

<thisElement someAttribute="blabla"/> 

UPDATE:

我我試圖找到一種方法來實現這一點,使用:

public override void WriteEndElement() 

但是我不能使用當前的WriteEndElement函數來知道我必須改變它,如果它甚至是可能的。

+0

標準壓縮將無法正常工作?如果沒有,我會想出一個答案。 – Amy 2011-01-05 05:49:23

+0

將使用xml的應用程序不是由我們製作的,我們已經要求對其進行更改,但它不是計劃很快就會更改,所以我們正在盡我們所能將其最小化:(並且該空間的更改爲其中一個是有百萬條目的文件,200MB的文件,300MB的一些文件,但這是目前的平均值 – Guapo 2011-01-05 09:47:06

+0

我知道這是一個完整的黑客想法,但是你可以用字符串替換它,把整個文件放在一個字符串中' strXML'。運行'strXML.Replace(「\」/>「,」\「/>」)''然後'XElement.Parse(strXML)'。 – 2011-01-06 02:08:58

回答

1

恐怕沒有重寫代碼的重要部分是不可能的。該空間在內部類中是硬編碼的,不可配置。

例如,內部XmlEncodedRawTextWriter.WriteEndElement()方法的代碼片段。

internal override void WriteEndElement(string prefix, string localName, string ns) 
{ 
    // snip... 
    else 
    { 
     this.bufPos--; 
     this.bufChars[this.bufPos++] = ' '; // the space is hard coded 
     this.bufChars[this.bufPos++] = '/'; 
     this.bufChars[this.bufPos++] = '>'; 
    } 
} 

,你有,我能想到的一些選項來解析XML輸出到搜索結束標記手動刪除空間,實現自己的XML作家所以它不包括這個空間裏,或編寫一個包裝類,以便在寫入結束元素時使用反射來修改內部緩衝區。


這裏有一個擴展方法可以做到這一點。只是要警告,這不是便攜式的。它也不能保證適用於所有情況,儘管它似乎適用於簡單情況。我不認爲在這裏做什麼會破壞作者的狀態,但使用您自己的風險

public static class XmlWriterExtensions 
{ 
    private static readonly Func<XmlWriter, object> get_writer; 
    private static readonly Func<object, char[]> get_bufChars; 
    private static readonly Func<object, int> get_bufPos; 
    private static readonly Action<object, int> set_bufPos; 

    static XmlWriterExtensions() 
    { 
     var asm = Assembly.GetAssembly(typeof(XmlWriter)); 
     var xmlWellFormedWriterType = asm.GetType("System.Xml.XmlWellFormedWriter"); 
     var flags = BindingFlags.NonPublic | BindingFlags.Instance; 
     var writerField = xmlWellFormedWriterType.GetField("writer", flags); 
     get_writer = w => writerField.GetValue(w); 
     var xmlEncodedRawTextWriterType = asm.GetType("System.Xml.XmlEncodedRawTextWriter"); 
     var bufCharsField = xmlEncodedRawTextWriterType.GetField("bufChars", flags); 
     var bufPosField = xmlEncodedRawTextWriterType.GetField("bufPos", flags); 
     get_bufChars = w => (char[])bufCharsField.GetValue(w); 
     get_bufPos = w => (int)bufPosField.GetValue(w); 
     set_bufPos = (w, i) => bufPosField.SetValue(w, i); 

    } 

    public static void TrimElementEnd(this XmlWriter writer) 
    { 
     var internalWriter = get_writer(writer); 
     char[] bufChars = get_bufChars(internalWriter); 
     int bufPos = get_bufPos(internalWriter); 
     if (bufPos > 3 && bufChars[bufPos - 3] == ' ' && bufChars[bufPos - 2] == '/' && bufChars[bufPos - 1] == '>') 
     { 
      bufChars[bufPos - 3] = '/'; 
      bufChars[bufPos - 2] = '>'; 
      bufPos--; 
      set_bufPos(internalWriter, bufPos); 
     } 
    } 
} 

// usage: 
Console.OutputEncoding = Encoding.UTF8; 
using (var writer = XmlWriter.Create(Console.Out)) 
{ 
    writer.WriteStartElement("Foo"); 
    writer.WriteElementString("Bar", null); 
    writer.TrimElementEnd(); 
    writer.WriteElementString("Baz", null); 
    writer.WriteEndElement(); 
} 

 

<?xml version="1.0" encoding="utf-8"?><Foo><Bar/><Baz /></Foo> 
+0

這是什麼我目前正在解析輸出的XML來搜索結束標籤,以刪除空間' – Guapo 2011-01-06 02:04:39

+0

@Guapo:敬請期待,我會努力寫下最後一個選項。這是可能的,但非常黑客。 – 2011-01-06 02:21:33

+0

@Jeff我期待着它的實施將是一個保佑。 – Guapo 2011-01-06 02:30:15