将XhtmlTextWriter与XmlTextReader一起使用

时间:2013-10-21 17:28:50

标签: c# .net linq parsing xmltextreader

在阅读this article后,我决定使用XmlDocument更新以下代码(使用XmlReader):

渲染控件

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;
}

的问题:

  • 是否有优化现有代码的空间?

  • 如何从XmlTextReaderControlStringWriter对象直接实例化XhtmlTextWriter?或者我是否真的需要首先将其呈现为string然后实例化XmlTextReader

修改

根据Jon Skeet的回答,这是更新。我们的想法是在每个元素之后删除换行符:

在美化之前:

<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声明。

1 个答案:

答案 0 :(得分:2)

  

是否有优化现有代码的空间?

绝对。我改变的第一个地方与加载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();
}

您可以使用传递到StringBuilder的{​​{1}}进一步优化此功能,但我还没有完全掌握您的代码。 (这是在早上的第一杯咖啡之前。)

就XML处理本身而言,您目前正在通过在每个子节点中设置RecursiveOperation节点(递归)来进行大量重组。我怀疑如果我能更好地掌握你在做什么,改变整个方法是可行的。鉴于这是OuterXml实际上没有的功能(这没有意义),目前还不清楚您是否应该注意另一篇文章。

  

我如何从Control,StringWriter或XhtmlTextWriter对象直接实例化XmlTextReader?或者我是否真的需要首先将其呈现为字符串然后实例化XmlTextReader?

目前尚不清楚从这些对象中创建XmlReader甚至意味着什么 - 它们本身并不是XML数据的。我觉得你已经看起来对我来说很合理了。

如果您仍然关注性能,则应避免猜测并使用分析器来衡量时间。你应该首先设定一个目标,否则你不知道何时完成优化。