C # - возможно ли (и как) выполнить XSL-преобразования с использованием SgmlReader - PullRequest
6 голосов
/ 30 ноября 2010

Мне нужно было преобразовать содержимое веб-страницы 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. Процесс преобразования требует дополнительной обработки CPU иодна и та же иерархия обходится дважды (теоретически излишне).

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

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

Ответы [ 2 ]

3 голосов
/ 30 ноября 2010

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

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

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

1 голос
/ 30 ноября 2010

Вы пытались использовать 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);

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

...