C# - возможно ли (и как) выполнить XSL-преобразования, используя SgmlReader

Мне нужно было преобразовать содержимое веб-страницы HTML с помощью XSLT. Поэтому я использовал SgmlReader и написал фрагмент, показанный ниже (я подумал, в конце концов, это тоже XmlReader...)

XmlReader xslr = XmlReader.Create(new StringReader(
    "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
    "<xsl:stylesheet xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" version=\"1.0\">" +
    "<xsl:output method=\"xml\" encoding=\"UTF-8\" version=\"1.0\" />" +
    "<xsl:template match=\"/\">" +
    "<XXX xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"><xsl:value-of select=\"count(//br)\" /></XXX>" +
    "</xsl:template>" +
    "</xsl:stylesheet>"));

XslCompiledTransform xslt = new XslCompiledTransform();
xslt.Load(xslr);

using (SgmlReader html = new SgmlReader())
{
    StringBuilder sb = new StringBuilder();
    using (TextWriter sw = new StringWriter(sb))
    using (XmlWriter xw = new XmlTextWriter(sw))
    {
        html.InputStream = new StringReader(Resources.html_orig);
        html.DocType = "HTML";

        try
        {
            xslt.Transform(html, xw);
            string output = sb.ToString();
            System.Console.WriteLine(output);
        }
        catch (Exception exc)
        {
            System.Console.WriteLine("{0} : {1}", exc.GetType().Name, exc.Message);
            System.Console.WriteLine(exc.StackTrace);
        }
    }
}

Тем не менее, я получаю это сообщение об ошибке

NullReferenceException : Object reference not set to an instance of an object.
   at MS.Internal.Xml.Cache.XPathDocumentBuilder.Initialize(XPathDocument doc, IXmlLineInfo lineInfo, String baseUri, LoadFlags flags)
   at MS.Internal.Xml.Cache.XPathDocumentBuilder..ctor(XPathDocument doc, IXmlLineInfo lineInfo, String baseUri, LoadFlags flags)
   at System.Xml.XPath.XPathDocument.LoadFromReader(XmlReader reader, XmlSpace space)
   at System.Xml.XPath.XPathDocument..ctor(XmlReader reader, XmlSpace space)
   at System.Xml.Xsl.Runtime.XmlQueryContext.ConstructDocument(Object dataSource, String uriRelative, Uri uriResolved)
   at System.Xml.Xsl.Runtime.XmlQueryContext..ctor(XmlQueryRuntime runtime, Object defaultDataSource, XmlResolver dataSources, XsltArgumentList argList, WhitespaceRuleLookup wsRules)
   at System.Xml.Xsl.Runtime.XmlQueryRuntime..ctor(XmlQueryStaticData data, Object defaultDataSource, XmlResolver dataSources, XsltArgumentList argList, XmlSequenceWriter seqWrt)
   at System.Xml.Xsl.XmlILCommand.Execute(Object defaultDocument, XmlResolver dataSources, XsltArgumentList argumentList, XmlSequenceWriter results)
   at System.Xml.Xsl.XmlILCommand.Execute(Object defaultDocument, XmlResolver dataSources, XsltArgumentList argumentList, XmlWriter writer, Boolean closeWriter)
   at System.Xml.Xsl.XmlILCommand.Execute(XmlReader contextDocument, XmlResolver dataSources, XsltArgumentList argumentList, XmlWriter results)
   at System.Xml.Xsl.XslCompiledTransform.Transform(XmlReader input, XmlWriter results)

Я нашел способ обойти это путем преобразования HTML в XML и последующего применения преобразования, но это неэффективное решение, потому что:

  1. Промежуточный вывод XHTML направляется в буфер, поэтому требуется дополнительная память
  2. Процесс преобразования требует дополнительной обработки ЦП, и одна и та же иерархия обходится дважды (теоретически излишне).

Итак (поскольку я знаю, что сообщество Stackru всегда дает отличные ответы, тогда как другие форумы по C# меня полностью разочаровали ;o) Я буду искать отзывы и предложения для непосредственного выполнения XSL- преобразований с использованием HTML (даже если SgmlReader необходимо заменить другим). подобная библиотека).

Заранее спасибо

2 ответа

Даже если SgmlReader класс расширяет XmlReader класс это не значит, что он также ведет себя как XmlReader,

Технически это также не имеет смысла, что SgmlReader это подкласс XmlReaderпросто потому, что SGML является надмножеством XML, а не подмножеством.

Вы не писали о цели вашего преобразования, но в целом HTML Agility Pack - хороший вариант для манипулирования HTML.

Вы пытались использовать HTML Agility Pack вместо SgmlReader? Вы можете загрузить html в него и напрямую выполнить преобразование для него. Я не уверен, что если XML-документ создается внутренне, хотя кажется, что он не так, вы, вероятно, захотите сравнить использование памяти и ЦП с методом преобразования, который вы пытались и отбрасывали.

//You already have your xslt loaded into var xslt...

HtmlDocument doc = new HtmlDocument();
doc.Load( ... );  //load your HTML doc, or use LoadXML from a string, etc  
xslt.Transform(doc, xw);

Смотрите также этот вопрос: Как использовать HTML Agility Pack

Другие вопросы по тегам