2013-10-21 43 views
2

讀取this article後,我已決定與XmlReader更新(使用XmlDocument)以下代碼:使用XhtmlTextWriter與XmlTextReader的

呈現控件

public string Rendering(Control baseControl) 
{ 
    StringBuilder stringBuilder = new StringBuilder(); 

    using (StringWriter stringWriter = new StringWriter(stringBuilder)) 
    using (XhtmlTextWriter htmlWriter = new XhtmlTextWriter(stringWriter)) 
    { 
     baseControl.RenderControl(htmlWriter); 

     return PretifyWithNewlines(stringBuilder.ToString()); 
    } 
} 

每個節點之後添加新行

private string PretifyWithNewlines(string minifiedMarkup) 
{ 
    XmlDocument xmlDocument = new XmlDocument(); 
    xmlDocument.XmlResolver = null; 

    try 
    { 
     xmlDocument.LoadXml("<base>" + minifiedMarkup + "</base>"); 
    } 
    catch // when minifiedMarkup contains the whole HTML with DTD tag defined, 
    {         // it throws an exception with <base> 
     xmlDocument.LoadXml(minifiedMarkup); 
    } 

    return recursiveOperation(xmlDocument.ChildNodes) 
      .Replace(Environment.NewLine + Environment.NewLine, Environment.NewLine) 
      .Replace(Environment.NewLine + "<base>" + Environment.NewLine, "") 
      .Replace(Environment.NewLine + "</base>" + Environment.NewLine, ""); 

} 

遞歸遍歷每個節點和種植新元素

private static string recursiveOperation(XmlNodeList xmlNodeList) 
{ 
    string result = ""; 

    foreach (XmlNode currentNode in xmlNodeList) 
    { 
     XmlNode clonedNode = currentNode; 

     string interimMarkup = recursiveOperation(currentNode.ChildNodes); 
     try 
     { 
      clonedNode.InnerXml = interimMarkup; 
     } 
     finally 
     { 
      result += Environment.NewLine + clonedNode.OuterXml + Environment.NewLine; 
     } 
    } 
    return result; 
} 

問題:

  • 是否有優化現有代碼的房間?

  • 我該怎麼去直接實例化XmlTextReaderControl,StringWriterXhtmlTextWriter對象?或者我真的需要先將它渲染爲string,然後實例化XmlTextReader

編輯

按喬恩斯基特的答案,這裏是更新。我們的想法是要破滅的每個元素後換行:

美化前:

<div class="tag"><span>text<span class="another-span"></span></span></div><div>Text<img src="some/relative/URL/" />namely</div> 

美化後:

<div class="tag"> 
<span> 
text 
<span class="another-span"></span> 
</span> 
</div> 
<div> 
Text 
<img src="some/relative/URL/" /> 
namely 
</div> 

通知而一切擴展(與子節點)span.another-span保持怎樣崩潰了。縮進將由Visual Studio聲明。

+0

你是純粹出於性能原因這麼做嗎?你有證據表明加載XML實際上是緩慢的部分嗎?我用這個代碼做的第一件事是用'StringBuilder'替換字符串連接(傳遞給'recursiveOperation',所以只有其中一個)。 –

+0

@JonSkeet,是的表現是這裏主要關心的。正如文章中提到的那樣,「XmlTextReader」和「Linq to Xml」是獲勝者。我認爲'XmlDocument'是緩慢的和種類貶值。 – Annie

+0

那麼你已經有了一個基準測試工具,所以你可以*測量*你的表現?如果你還沒有,那麼在開始修改代碼之前,這是第一件要做的事情。 'XmlDocument'肯定不會被棄用,儘管我不會在新代碼中使用它,除非必須。我懷疑你的很多時間實際上會花在重新分析(當你設置InnerXml屬性時)。 –

回答

2

Is there a room for optimizing the existing code?

絕對。我要改變的第一個地方與加載XML無關 - 它是字符串連接。我想你的recursiveOperation方法更改爲:

private static string RecursiveOperation(XmlNodeList xmlNodeList) 
{ 
    StringBuilder result = new StringBuilder(); 

    foreach (XmlNode currentNode in xmlNodeList) 
    { 
     XmlNode clonedNode = currentNode; 

     // Remove try/finally block - if an exception is thrown your 
     // result will be lost anyway 
     string interimMarkup = RecursiveOperation(currentNode.ChildNodes); 
     clonedNode.InnerXml = interimMarkup; 
     result.Append(Environment.NewLine) 
       .Append(clonedNode.OuterXml) 
       .Append(Environment.NewLine); 
    } 
    return result.ToString(); 
} 

這是可能的,你可以優化該再使用傳入RecursiveOperation一個StringBuilder,但我還沒有完全得到了你的代碼交手,足以尚未說。 (這是早晨的第一杯咖啡。)

就XML處理本身而言,您目前通過在每個子節點(遞歸地)中設置OuterXml節點來進行大量的重新分析。我懷疑,如果我能更好地掌握自己在做什麼,那麼改變整個方法是可行的。鑑於這是XmlReader實際上沒有的功能(這沒有意義),目前尚不清楚您應該多注意其他文章。

How would I go about directly instantiating XmlTextReader from Control, StringWriter or XhtmlTextWriter object? Or do I really need to render it as a string first then instantiate XmlTextReader?

目前還不清楚是什麼,甚至將意味着創建的任何對象的XmlTextReader - 他們不是固有的XML數據源。我認爲你對我已經看起來很合理。

如果您仍然關注性能,您應該避免猜測,並使用分析器來衡量時間在何處。你應該首先設定一個目標,否則你不會知道什麼時候你已經完成優化。

+0

@Annie:那麼你已經有哪些性能測試?你能夠衡量你實際上從這些方面獲得的改進嗎? –

+0

目前,我只是在我的單元測試案例中進行壓力測試。就像使用隨機參數調用控件生成器來構建Control對象,然後渲染控件來生成標記字符串一樣。當建立控制時,某些背景是未知的,這阻礙了我精心製作新線。這就是爲什麼我正在做這個*後處理*。 – Annie

+1

所以不是隨機地做這件事,爲什麼不找到*逼真的測試用例,找出你需要它們的速度有多快,然後再測試一下。然後你會知道你有多接近你的要求。 –