Действительно ли использованием является StringBuilder для записи XML хорошо?

Это чувствует себя грязным. Но возможно это не... это в порядке для использования StringBuilder для записи XML? Мой инстинкт пищеварительного тракта говорит, "хотя это чувствует себя неправильным, это, вероятно, довольно проклятое производительный, потому что это не загружает дополнительные библиотеки, и наверху это не делает любых дополнительных вызовов метода, которые вызывает XmlWriter". Также кажется, что это - просто меньше кода в целом. Каково преимущество в XmlWriter?

Вот то, на что это похоже. Я создаю документ OpenSearch XML на основе домена, от которого Вы входите.

public void ProcessRequest(HttpContext context)
{
    context.Response.ContentType = "text/xml";

    string domain = WebUtils.ReturnParsedSourceUrl(null); //returns something like www.sample.com
    string cachedChan = context.Cache[domain + "_opensearchdescription"] as String;

    if (cachedChan == null)
    {
        StringBuilder sb = new StringBuilder();
        sb.Append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
        sb.Append("<OpenSearchDescription xmlns=\"http://a9.com/-/spec/opensearch/1.1/\" xmlns:moz=\"http://www.mozilla.org/2006/browser/search/\">");
        sb.Append("    <ShortName>Search</ShortName>");
        sb.Append("    <Description>Use " + domain + " to search.</Description>");
        sb.Append("    <Contact>contact@sample.com</Contact>");
        sb.Append("    <Url type=\"text/html\" method=\"get\" template=\"http://" + domain + "/Search.aspx?q={searchTerms}\" />");
        sb.Append("    <moz:SearchForm>http://" + domain + "/Search.aspx</moz:SearchForm>");
        sb.Append("    <Image height=\"16\" width=\"16\" type=\"image/x-icon\">http://" + domain + "/favicon.ico</Image>");
        sb.Append("</OpenSearchDescription>");

        cachedChan = sb.ToString();

        context.Cache.Insert(domain + "_opensearchdescription", cachedChan, null, DateTime.Now.AddDays(14), TimeSpan.Zero);
    }

    context.Response.Write(cachedChan);
}

Продолжение, ~2 года спустя я понял, что, что я означал говорить и полностью не удался сказать, это: каково преимущество ртов кода с помощью классов XML для генерации этого файла, по сравнению только с использованием строк? Есть ли один? Действительно ли это хуже, чем (например), пример John Saunder?

Я использовал метод Jim Schubert, выбирающий 'Я могу считать это, и он имеет смысл' вместо того, чтобы соперничать за 'правильность'. Я рад, что сделал. Нет ничего неправильно с примером John Saunder - но я чувствовал, что это был путь, властный для того, что я пытался выполнить. Прагматизм? Возможно.

11
задан Jack Lawson 9 January 2012 в 23:03
поделиться

8 ответов

Это очень неправильно. Используйте один из .NET API, который понимает XML, для написания XML.

Использование System.Xml.XmlWriter не вызовет проблем с производительностью из-за загрузки «любых дополнительных библиотек».


Причина использования XML API заключается в том, что они понимают правила XML. Например, они будут знать набор символов, которые необходимо заключить в кавычки внутри элемента, и другой набор, который нужно заключить в кавычки внутри атрибута.

Это может не быть проблемой в вашем случае: возможно, вы уверены, что в домене не будет никаких символов, которые нужно будет заключать в кавычки. В любой более широкой ситуации лучше всего позволить API XML выполнять XML - а они умеют это делать - чтобы вам не приходилось делать это самостоятельно.


Вот пример того, как легко создать действительный XML с помощью LINQ to XML:

public static string MakeXml()
{
    XNamespace xmlns = "http://a9.com/-/spec/opensearch/1.1/";
    XNamespace moz = "http://www.mozilla.org/2006/browser/search/";
    string domain = "http://localhost";
    string searchTerms = "abc";
    var doc = new XDocument(
        new XDeclaration("1.0", "UTF-8", "yes"),
        new XElement(
            xmlns + "OpenSearchDescription",
            new XElement(xmlns + "ShortName", "Search"),
            new XElement(
                xmlns + "Description",
                String.Format("Use {0} to search.", domain)),
            new XElement(xmlns + "Contact", "contact@sample.com"),
            new XElement(
                xmlns + "Url",
                new XAttribute("type", "text/html"),
                new XAttribute("method", "get"),
                new XAttribute(
                    "template",
                    String.Format(
                        "http://{0}/Search.aspx?q={1}",
                        domain,
                        searchTerms))),
            new XElement(
                moz + "SearchForm",
                String.Format("http://{0}/Search.aspx", domain)),
            new XElement(
                xmlns + "Image",
                new XAttribute("height", 16),
                new XAttribute("width", 16),
                new XAttribute("type", "image/x-icon"),
                String.Format("http://{0}/favicon.ico", domain))));
    return doc.ToString(); // If you _must_ have a string
}
15
ответ дан 3 December 2019 в 06:20
поделиться

Пожалуйста, не используйте StringBuilder. Любой, кто говорит вам, что это значительно быстрее, не предоставил вам никаких реальных данных. Разница в скорости несущественна, и впереди вас ждет кошмар ремонта.

ПОЗНАКОМЬТЕСЬ: StringBuilder vs XmlTextWriter

1
ответ дан 3 December 2019 в 06:20
поделиться

Ваша интуиция ошибочна. Независимо от того, пишете ли вы XML вручную или используете XmlWriter, наиболее эффективным способом отправки XML в HttpResponse будет добавление текста непосредственно в Response. Создание всей строки и последующая отправка тратит ресурсы впустую.

0
ответ дан 3 December 2019 в 06:20
поделиться

Вы можете создать сильно типизированный объект и использовать классы XmlSerialization для генерации данных xml

-1
ответ дан 3 December 2019 в 06:20
поделиться

Ну, это тонко. Как и при любой другой оптимизации в жизни, вы нарушаете границы абстракции и платите за это цену, чтобы получить эффективность.

По моему опыту, это действительно значительно быстрее, не из-за загрузки библиотек, конечно (если что, это сделает его медленнее), а потому что это экономит на выделении строк. Я не помню точно, насколько быстрее, извините. Измерить это с помощью профилировщика будет сложно, потому что вы также экономите на сборке мусора.

Но не вините меня, когда вам придется иметь дело с кодировками, экранированием и черт знает чем еще, и не забудьте внимательно прочитать стандарт XML, прежде чем выпускать эти XML куда-либо.

1
ответ дан 3 December 2019 в 06:20
поделиться

Будут ли переменные домена возвращать символы "&" или другой символ, который необходимо закодировать? Вы можете потратить время на защитное программирование и проверить свой вклад.

0
ответ дан 3 December 2019 в 06:20
поделиться

Что ж, в написании XML-строк вручную нет ничего плохого, но это гораздо более подвержено ошибкам. Если у вас нет веских причин для повышения производительности (то есть вы измерили и обнаружили, что форматирование XML является узким местом), я бы вместо этого использовал классы XML. Вы сэкономите много времени на отладку и разработку.

Кстати, почему вы смешиваете динамические строковые операции с вызовами построителя? Вместо:

sb.Append("    <Description>Use " + domain + " to search.</Description>"); 

попробуйте следующее:

sb.Append("    <Description>Use ").Append(domain).Append(" to search.</Description>");
1
ответ дан 3 December 2019 в 06:20
поделиться

Я бы не стал использовать для этого StringBuilder, потому что вам нужно вызывать метод Append для каждой строки. Вы можете использовать XmlWriter, и это не повредит производительности.

Вы можете уменьшить объем генерируемого кода IL, выполнив следующие действия:

private const string XML_TEMPLATE = @"<?xml version=\"1.0\" encoding=\"UTF-8\"?>
<OpenSearchDescription xmlns=\"http://a9.com/-/spec/opensearch/1.1/\" xmlns:moz=\"http://www.mozilla.org/2006/browser/search/\">
    <ShortName>Search</ShortName>
    <Description>Use {0} to search.</Description>
    <Contact>contact@sample.com</Contact>
    <Url type=\"text/html\" method=\"get\" template=\"http://{0}/Search.aspx?q={searchTerms}\" />
    <moz:SearchForm>http://{0}/Search.aspx</moz:SearchForm>
    <Image height=\"16\" width=\"16\" type=\"image/x-icon\">http://{0}/favicon.ico</Image>
</OpenSearchDescription>";

И в вашем методе:

    if (cachedChan == null)
    {
        cachedChan = String.Format(XML_TEMPLATE, domain);

        context.Cache.Insert(domain + "_opensearchdescription", 
               cachedChan, null, DateTime.Now.AddDays(14), TimeSpan.Zero);
    }

Это должно хорошо сработать для вас, потому что метод, который у вас есть сейчас, должен будет создать новую строку для каждого вызова StringBuilder.Append (), затем вызовите этот метод. Вызов String.Format генерирует только 17 строк кода IL, по сравнению с StringBuilder, генерирующим 8 строк кода ctor, а затем 6 строк для каждого вызова Append. Хотя при сегодняшних технологиях лишние 50 строк IL не будут заметны.

2
ответ дан 3 December 2019 в 06:20
поделиться
Другие вопросы по тегам:

Похожие вопросы: