Использует 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>[email protected]</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 года спустя
Я понял, что я хотел сказать, и полностью не смог сказать, что это: какова польза от gobs кода с использованием классов XML для создания этого файла, а просто с использованием строк? Есть ли это? Это хуже, чем (например) пример Джона Саундера?
Я использовал метод Джима Шуберта, выбрав "Я могу это прочитать, и это имеет смысл" вместо того, чтобы бороться за "правильность". Я рад, что сделал. Нет ничего плохого в том, что касается примера Джона Саундера, но я чувствовал, что это было способно овладеть тем, что я пытался достичь. Прагматизм? Может быть.
Ответы
Ответ 1
Это очень неправильно. Используйте один из .NET API, которые понимают XML для записи XML.
Использование System.Xml.XmlWriter
не приведет к какой-либо проблеме с производительностью при загрузке "дополнительных библиотек".
Причиной использования XML-API является то, что они понимают правила XML. Например, они будут знать набор символов, которые должны быть указаны внутри элемента, и другой набор, который должен быть указан внутри атрибута.
Это может не быть проблемой в вашем случае: возможно, вы уверены, что domain
не будет содержать никаких символов, которые должны быть указаны. В любой более широкой ситуации лучше всего позволить XML API выполнять 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", "[email protected]"),
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
}
Ответ 2
Я бы не использовал 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>[email protected]</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 строк ИЛ не будут заметны.
Ответ 3
Ну, это тонко. Как и все другие оптимизации в жизни, вы нарушаете границы абстракции и платите за это, чтобы повысить эффективность.
По моему опыту, это действительно значительно быстрее, а не из-за загрузки библиотек, конечно (если что-то, что сделает его медленнее), а потому, что оно сохраняет распределение строк. Я не помню точно, насколько быстрее, извините. Измерение его с помощью профилировщика будет затруднено, так как вы также сэкономите на расходах на сбор мусора.
Но, не обвиняйте меня, когда вам придется иметь дело с кодировками и побегами, а ад знает, что еще, и не забудьте внимательно прочитать XML-стандарт, прежде чем вывести эти XML из любого места.
Ответ 4
Ну, нет ничего плохого в том, чтобы вручную писать строки XML как таковые, но гораздо более подвержены ошибкам. Если у вас нет убедительной причины для создания производительности (т.е. Вы измерили и обнаружили, что форматирование XML является узким местом), я бы вместо этого использовал классы XML. Вы будете экономить много времени на отладку и разработку.
Как в стороне, почему вы смешиваете операции динамической строки с вашими вызовами строителя? Вместо:
sb.Append(" <Description>Use " + domain + " to search.</Description>");
попробуйте следующее:
sb.Append(" <Description>Use ").Append(domain).Append(" to search.</Description>");
Ответ 5
Пожалуйста, не используйте StringBuilder. Любой, кто говорит вам, что он значительно быстрее, не предоставил вам никаких реальных данных. Разница в скорости несущественна, и у вас будет кошмар господства перед вами.
У вас есть looK: StringBuilder vs XmlTextWriter
Ответ 6
Твоя кишка неправильна. Будь вы вручную пишете XML или используете XmlWriter, наиболее эффективным способом отправки XML в HttpResponse будет текст приложения непосредственно в ответ. Построение всей строки, а затем отправка ее ресурсов.
Ответ 7
Вернутся ли переменные домена "&" символов или другого символа, который должен быть закодирован? Вы можете потратить время на защитное программирование и подтвердить свой ввод.
Ответ 8
Вы можете создать строго типизированный объект и использовать классы XmlSerialization для генерации данных xml