Преобразование .NET XSLT, это действительно потоковое? - PullRequest
3 голосов
/ 11 июня 2009

У меня есть XML, из которого мне нужно удалить пустые элементы. Я пытаюсь избежать использования DOM и пытаюсь сделать это в виде потоков. У меня есть этот код, но я не совсем уверен, насколько это правильно и оптимизировано.

StringBuilder xslt = new StringBuilder();
xslt.Append(@"<?xml version=""1.0"" encoding=""UTF-8""?>");
xslt.Append(@"<xsl:stylesheet version=""1.0"" xmlns:xsl=""http://www.w3.org/1999/XSL/Transform"">");
xslt.Append(@"<xsl:output method=""xml"" version=""1.0"" encoding=""UTF-8"" indent=""yes""/>");
xslt.Append(@"<xsl:template match=""*"">");
xslt.Append(@"<xsl:if test=""count(@*) > 0 or count(node()) > 0"">");
xslt.Append(@"<xsl:copy>");
xslt.Append(@"<xsl:apply-templates select=""@* | node()""/>");
xslt.Append(@"</xsl:copy>");
xslt.Append(@"</xsl:if>");
xslt.Append(@"</xsl:template>");
xslt.Append(@"<xsl:template match=""@* | text()"">");
xslt.Append(@"<xsl:copy/>");
xslt.Append(@"</xsl:template>");
xslt.Append(@"</xsl:stylesheet>");

StringBuilder resultString = new StringBuilder();
XmlTextWriter xmlWriter = new XmlTextWriter(new StringWriter(resultString));
XmlTextReader xmlReader = new XmlTextReader(new StringReader(xmlString));

System.Xml.Xsl.XslCompiledTransform xslTransform = new System.Xml.Xsl.XslCompiledTransform();
xslTransform.Load(new XmlTextReader(new StringReader(xslt.ToString())));
xslTransform.Transform(xmlReader, xmlWriter);
xmlReader.Close();

xmlWriter.Flush();
xmlWriter.Close();

Это хороший способ сделать это?

Ответы [ 2 ]

6 голосов
/ 11 июня 2009

Да, вы используете потоки, но вы теряете одно из преимуществ потоков: не загружать весь ввод и вывод XML сразу в память.

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

Решение состоит в том, чтобы избежать StringReader / StringWriter и вместо этого использовать соответствующую реализацию потока в зависимости от того, откуда следует читать и отправлять XML. Например:

  • Если вы хотите преобразовать в / из XML-файл, используйте FileStreams.
  • Если вы отправляете через сокет / HTTP-соединение, используйте поток, предоставленный вашим объектом соединения.

Кроме того, загрузка XSLT из встроенных строк, как правило, не очень хорошая идея (ее сложнее поддерживать), но я не думаю, что это приведет к проблемам с производительностью (если XSLT действительно не очень большой). Для лучшей управляемости я бы порекомендовал хранить XSLT в другом файле. Файл может быть либо загружен из файловой системы (с помощью FileStream), либо он также может быть сохранен внутри скомпилированного DLL-файла как «встроенный ресурс» и загружен с помощью assembly.GetManifestResourceStream().

3 голосов
/ 11 июня 2009

Почему вы используете StringBuilder для создания этого XSL-текста? Если XSL исправлен, почему бы просто не оставить его как константную строку?

Например,

string xslt =
    @"<?xml version=""1.0"" encoding=""UTF-8""?>" +
     "<xsl:stylesheet version=""1.0"" xmlns:xsl=""http://www.w3.org/1999/XSL/Transform"">" +
     "<xsl:output method=""xml"" version=""1.0"" encoding=""UTF-8"" indent=""yes""/>" +
     "<xsl:template match=""*"">" +
     "<xsl:if test=""count(@*) > 0 or count(node()) > 0"">" +
     "<xsl:copy>" +
     "<xsl:apply-templates select=""@* | node()""/>" +
     "</xsl:copy>" +
     "</xsl:if>" +
     "</xsl:template>" +
     "<xsl:template match=""@* | text()"">" +
     "<xsl:copy/>" +
     "</xsl:template>" +
     "</xsl:stylesheet>";


StringBuilder resultString = new StringBuilder();
XmlTextWriter xmlWriter = new XmlTextWriter(new StringWriter(resultString));
XmlTextReader xmlReader = new XmlTextReader(new StringReader(xmlString));

System.Xml.Xsl.XslCompiledTransform xslTransform = new System.Xml.Xsl.XslCompiledTransform();
xslTransform.Load(new XmlTextReader(new StringReader(xslt)));
xslTransform.Transform(xmlReader, xmlWriter);
xmlReader.Close();

xmlWriter.Flush();
xmlWriter.Close();

Кроме того, если бы это был я, я бы поместил предложение using () вокруг xmlReader и xmlWriter. Я думаю, что они одноразовые. например,

StringBuilder resultString = new StringBuilder();
using (XmlTextWriter xmlWriter = new XmlTextWriter(new StringWriter(resultString)))
{
    using (XmlTextReader xmlReader = new XmlTextReader(new StringReader(xmlString)))
    {
        System.Xml.Xsl.XslCompiledTransform xslTransform = new System.Xml.Xsl.XslCompiledTransform();
        xslTransform.Load(new XmlTextReader(new StringReader(xslt)));
        xslTransform.Transform(xmlReader, xmlWriter);
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...