簡體   English   中英

C# - 是否可以(以及如何)使用 SgmlReader 執行 XSL 轉換

[英]C# - Is it possible (and how) to perform XSL transformations using SgmlReader

我需要使用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然后應用 transform 來解決此問題的方法,但這是一個低效的解決方案,因為:

  1. 中間XHTML輸出進入緩沖區,因此需要額外的內存
  2. 轉換過程需要額外的CPU處理,並且相同的層次結構被遍歷兩次(理論上是不必要的)。

所以(因為我知道StackOverflow社區總是提供很好的答案,而其他C#論壇讓我完全失望;o)我將尋找反饋和建議,以便直接使用HTML執行XSL轉換(即使SgmlReader需要被另一個替換類似的庫)。

即使SgmlReader類擴展了XmlReader類,也不意味着它的行為也像XmlReader

從技術上講, SgmlReaderXmlReader的子類也是沒有意義的,因為 SGML 是 XML 的超集而不是子集。

您沒有說明轉換的目的,但總的來說, HTML Agility Pack是處理 HTML 的不錯選擇。

您是否嘗試過使用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 Agility pack

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM