HtmlAgilityPack 可以处理 xsl 文件附带的 xml 文件来渲染 html 吗?

发布于 2024-10-25 04:57:40 字数 846 浏览 4 评论 0原文

我想知道 HtmlAgilityPack 读取包含 xsl 文件的 xml 文件以呈现 html 的最佳方式。 HtmlDocument 类上是否有任何设置可以帮助实现此目的,或者我是否必须找到一种方法来执行转换,然后再使用 HtmlAgiliyPack 加载它?如果是后者,有人知道用于这种转换的好的库或方法吗?下面是一个网站示例,该网站返回带有 xls 文件的 xml 以及我想要使用的代码。

var uri = new Uri("http://www.skechers.com/");
var request = (HttpWebRequest)WebRequest.Create(url);
var cookieContainer = new CookieContainer();

request.CookieContainer = cookieContainer;
request.UserAgent = @"Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.5) Gecko/20091102 Firefox/3.5.5";
request.Method = "GET";
request.AllowAutoRedirect = true;
request.Timeout = 15000;

var response = (HttpWebResponse)request.GetResponse();
var page = new HtmlDocument();
page.OptionReadEncoding = false;
var stream = response.GetResponseStream();
page.Load(stream); 

这段代码不会引发任何错误,但解析的是 xml,而不是转换,这正是我想要的。

I was wondering the best way for HtmlAgilityPack to read an xml file that includes an xsl file to render html. Are there any settings on the HtmlDocument class that would assist in this, or do I have to find a way to execute the transformation before loading it with HtmlAgiliyPack? If yes for the latter, anybody know of a good library or method for such a transformation? Below is an example of a website that returns xml with xls file and the code that I would like to use.

var uri = new Uri("http://www.skechers.com/");
var request = (HttpWebRequest)WebRequest.Create(url);
var cookieContainer = new CookieContainer();

request.CookieContainer = cookieContainer;
request.UserAgent = @"Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.5) Gecko/20091102 Firefox/3.5.5";
request.Method = "GET";
request.AllowAutoRedirect = true;
request.Timeout = 15000;

var response = (HttpWebResponse)request.GetResponse();
var page = new HtmlDocument();
page.OptionReadEncoding = false;
var stream = response.GetResponseStream();
page.Load(stream); 

This code does not throw any errors, but the xml is what gets parsed and not the transformation, which is what I want.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

柒七 2024-11-01 04:57:40

Html Agility Pack 可以在两点上为您提供帮助:

1)更容易获得 Xml 处理指令,因为它将 PI 数据解析为 Html,因此会将其转换为属性

2)HtmlDocument 实现 IXPathNavigable,因此可以直接转换通过 .NET Xslt 转换引擎。

这是一段有效的代码。我必须添加一个特定的 XmlResover 才能正确处理 Xslt 转换,但我认为这是特定于这个 skechers 案例的。

public static void DownloadAndProcessXml(string url, string userAgent, string outputFilePath)
{
    using (XmlTextWriter writer = new XmlTextWriter(outputFilePath, Encoding.UTF8))
    {
        DownloadAndProcessXml(url, userAgent, writer);
    }
}

public static void DownloadAndProcessXml(string url, string userAgent, XmlWriter output)
{
    UserAgentXmlUrlResolver resolver = new UserAgentXmlUrlResolver(url, userAgent);

    // WebClient is an easy to use class.
    using (WebClient client = new WebClient())
    {
        // download Xml doc. set User-Agent header or the site won't answer us...
        client.Headers[HttpRequestHeader.UserAgent] = resolver.UserAgent;
        HtmlDocument xmlDoc = new HtmlDocument();
        xmlDoc.Load(client.OpenRead(url));

        // determine xslt (note the xpath trick as Html Agility Pack does not support xml processing instructions)
        string xsltUrl = xmlDoc.DocumentNode.SelectSingleNode("//*[name()='?xml-stylesheet']").GetAttributeValue("href", null);

        // download Xslt doc
        client.Headers[HttpRequestHeader.UserAgent] = resolver.UserAgent;
        XslCompiledTransform xslt = new XslCompiledTransform();
        xslt.Load(new XmlTextReader(client.OpenRead(url + xsltUrl)), new XsltSettings(true, false), null);

        // transform Html/Xml doc into new Xml doc, easy as HtmlDocument implements IXPathNavigable
        // note the use of a custom resolver to overcome this Xslt resolve requests
        xslt.Transform(xmlDoc, null, output, resolver);
    }
}

// This class is needed during transformation otherwise there are errors.
// This is probably due to this very specific Xslt file that needs to go back to the root document itself.
public class UserAgentXmlUrlResolver : XmlUrlResolver
{
    public UserAgentXmlUrlResolver(string rootUrl, string userAgent)
    {
        RootUrl = rootUrl;
        UserAgent = userAgent;
    }

    public string RootUrl { get; set; }
    public string UserAgent { get; set; }

    public override object GetEntity(Uri absoluteUri, string role, Type ofObjectToReturn)
    {
        WebClient client = new WebClient();
        if (!string.IsNullOrEmpty(UserAgent))
        {
            client.Headers[HttpRequestHeader.UserAgent] = UserAgent;
        }
        return client.OpenRead(absoluteUri);
    }

    public override Uri ResolveUri(Uri baseUri, string relativeUri)
    {
        if ((relativeUri == "/") && (!string.IsNullOrEmpty(RootUrl)))
            return new Uri(RootUrl);

        return base.ResolveUri(baseUri, relativeUri);
    }
}

你这样称呼它:

    string url = "http://www.skechers.com/";
    string ua = @"Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.5) Gecko/20091102 Firefox/3.5.5";
    DownloadAndProcessXml(url, ua, "skechers.html");

Html Agility Pack can help you here on two points:

1) it's easier to get an Xml processing instruction with it as it parses the PI data as Html, so it will transform it into attributes

2) HtmlDocument implements IXPathNavigable so it can be transformed directly by the .NET Xslt transformation engine.

Here is a piece of code that works. I had to add a specific XmlResover to handle Xslt transform properly, but I think this is specific to this skechers case.

public static void DownloadAndProcessXml(string url, string userAgent, string outputFilePath)
{
    using (XmlTextWriter writer = new XmlTextWriter(outputFilePath, Encoding.UTF8))
    {
        DownloadAndProcessXml(url, userAgent, writer);
    }
}

public static void DownloadAndProcessXml(string url, string userAgent, XmlWriter output)
{
    UserAgentXmlUrlResolver resolver = new UserAgentXmlUrlResolver(url, userAgent);

    // WebClient is an easy to use class.
    using (WebClient client = new WebClient())
    {
        // download Xml doc. set User-Agent header or the site won't answer us...
        client.Headers[HttpRequestHeader.UserAgent] = resolver.UserAgent;
        HtmlDocument xmlDoc = new HtmlDocument();
        xmlDoc.Load(client.OpenRead(url));

        // determine xslt (note the xpath trick as Html Agility Pack does not support xml processing instructions)
        string xsltUrl = xmlDoc.DocumentNode.SelectSingleNode("//*[name()='?xml-stylesheet']").GetAttributeValue("href", null);

        // download Xslt doc
        client.Headers[HttpRequestHeader.UserAgent] = resolver.UserAgent;
        XslCompiledTransform xslt = new XslCompiledTransform();
        xslt.Load(new XmlTextReader(client.OpenRead(url + xsltUrl)), new XsltSettings(true, false), null);

        // transform Html/Xml doc into new Xml doc, easy as HtmlDocument implements IXPathNavigable
        // note the use of a custom resolver to overcome this Xslt resolve requests
        xslt.Transform(xmlDoc, null, output, resolver);
    }
}

// This class is needed during transformation otherwise there are errors.
// This is probably due to this very specific Xslt file that needs to go back to the root document itself.
public class UserAgentXmlUrlResolver : XmlUrlResolver
{
    public UserAgentXmlUrlResolver(string rootUrl, string userAgent)
    {
        RootUrl = rootUrl;
        UserAgent = userAgent;
    }

    public string RootUrl { get; set; }
    public string UserAgent { get; set; }

    public override object GetEntity(Uri absoluteUri, string role, Type ofObjectToReturn)
    {
        WebClient client = new WebClient();
        if (!string.IsNullOrEmpty(UserAgent))
        {
            client.Headers[HttpRequestHeader.UserAgent] = UserAgent;
        }
        return client.OpenRead(absoluteUri);
    }

    public override Uri ResolveUri(Uri baseUri, string relativeUri)
    {
        if ((relativeUri == "/") && (!string.IsNullOrEmpty(RootUrl)))
            return new Uri(RootUrl);

        return base.ResolveUri(baseUri, relativeUri);
    }
}

And you call it like this:

    string url = "http://www.skechers.com/";
    string ua = @"Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.5) Gecko/20091102 Firefox/3.5.5";
    DownloadAndProcessXml(url, ua, "skechers.html");
何时共饮酒 2024-11-01 04:57:40

您应该呈现 XML 和 XSLT 的输出。为此,您需要下载 XML,并且您已经完成了该操作。接下来解析 XML 以识别 XSL 引用。然后您需要下载 XSL 并将其应用到 XML 文档。

这些链接可能有用

You should render the output of the XML and XSLT. To do this you need to download the XML, and you've already done that. Next parse the XML to identify the XSL reference. Then you need to download the XSL and apply that to the XML document.

These links may be useful

惜醉颜 2024-11-01 04:57:40

这是我收到回复后最终使用的附加代码。请注意,只有当响应是“application/xml”时,这才有用,并且您必须在整个过程中检查对象的空实例。此外,FormAssetSrc 是一个私有函数,它获取 href 的值并确定它是协议、根还是文档相关,并创建完全限定的 uri。

var xmlStream = response.GetResponseStream();
var xmlDocument = new XPathDocument(xmlStream);
var styleNode = xmlDocument.CreateNavigator().SelectSingleNode("processing-instruction('xml-stylesheet')");
var hrefValue = Regex.Match((styleNode).Value, "href=(\"|')(?<url>.*?)(\"|')");
if(hrefValue.Success)
{
    var xslHref = FormAssetSrc(hrefValue.Groups["url"].Value, response.ResponseUri);
    var xslUri = new Uri(xslHref);
    var xslRequest = CreateWebRequest(xslUri);
    var xslResponse = (HttpWebResponse)xslRequest.GetResponse();
    var xslStream = new XPathDocument(xslResponse.GetResponseStream());
    var xslTransorm = new XslTransform();
    var sw = new System.IO.StringWriter();
    xslTransorm.Load(xslStream);
    xslTransorm.Transform(xmlDocument.CreateNavigator(), null, sw);
    page.Html.LoadHtml(sw.ToString());
}

Here is the additional code I ended up using once I received the response. Please note that this is only good if the response is "application/xml" and you will have to check for null instances of objects throughout. Also, FormAssetSrc is a private function that takes the value of the href and determines whether it is protocol, root, or document relative and creates the fully qualified uri.

var xmlStream = response.GetResponseStream();
var xmlDocument = new XPathDocument(xmlStream);
var styleNode = xmlDocument.CreateNavigator().SelectSingleNode("processing-instruction('xml-stylesheet')");
var hrefValue = Regex.Match((styleNode).Value, "href=(\"|')(?<url>.*?)(\"|')");
if(hrefValue.Success)
{
    var xslHref = FormAssetSrc(hrefValue.Groups["url"].Value, response.ResponseUri);
    var xslUri = new Uri(xslHref);
    var xslRequest = CreateWebRequest(xslUri);
    var xslResponse = (HttpWebResponse)xslRequest.GetResponse();
    var xslStream = new XPathDocument(xslResponse.GetResponseStream());
    var xslTransorm = new XslTransform();
    var sw = new System.IO.StringWriter();
    xslTransorm.Load(xslStream);
    xslTransorm.Transform(xmlDocument.CreateNavigator(), null, sw);
    page.Html.LoadHtml(sw.ToString());
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文