6

我需要使用XSLT转换HTML网页的内容 。因此我使用了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#论坛让我完全失望;o)我将寻找反馈和建议,以便直接使用HTML执行XSL转换(即使SgmlReader需要被另一个替换类似的库)。

4

2 回答 2

3

即使SgmlReader该类正在扩展XmlReader该类,但这并不意味着它的行为也像XmlReader.

SgmlReader从技术上讲,它是 的子类也没有意义,XmlReader因为 SGML 是 XML 的超集而不是子集。

您没有写下转换的目的,但总的来说,HTML Agility Pack是处理 HTML 的好选择。

于 2010-11-30T15:41:42.533 回答
1

您是否尝试过使用HTML Agility Pack而不是SgmlReader? 您可以将 html 加载到其中,并直接对其运行转换。不过,如果 XML 文档是在内部创建的,我并不肯定——尽管看起来好像不是,但您可能希望将内存和 CPU 使用率与您尝试并丢弃的转换方法进行比较。

//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 敏捷包

于 2010-11-30T15:26:52.030 回答