计算xml提要散列的最佳方法是什么?

本文关键字:最佳 方法 是什么 xml 计算 | 更新日期: 2023-09-27 18:12:09

我想检测提要是否发生了更改,我能想到的唯一方法是对xml文档的内容进行散列,并将其与提要的最后一个散列进行比较。

我使用XmlReader,因为SyndicationFeed使用它,所以理想情况下我不想加载联合提要,除非提要已经更新。

XmlReader reader = XmlReader.Create("http://www.extremetech.com/feed");
SyndicationFeed feed = SyndicationFeed.Load(reader);

计算xml提要散列的最佳方法是什么?

为什么不直接检查提要的LastUpdatedTime ?这是一种内在的方式,告诉你某件事是否是新的。不需要散列和存储散列,只需跟踪LastUpdatedTime并定期将其与最新的LastUpdatedTime进行比较:

using System;
using System.ServiceModel.Syndication;
using System.Xml;
public class MyClass
{
    private static DateTime _lastFeedTime = new DateTime(2011, 10, 10);
    public static void Main()
    {
        XmlReader reader = XmlReader.Create("http://www.extremetech.com/feed");
        SyndicationFeed feed = SyndicationFeed.Load(reader);
        if (feed.LastUpdatedTime.LocalDateTime > _lastFeedTime)
        {
            _lastFeedTime = feed.LastUpdatedTime.LocalDateTime;
            // load feed...
        }
    }
}

如果您真的想使用散列方式,您可以这样做:

var client = new WebClient();
var content = client.DownloadData("http://www.extremetech.com/feed");
var hash = MD5.Create().ComputeHash(content);
var hashString = Convert.ToBase64String(hash);
// you can then compare hashes and if changed load it this way
XmlReader reader = XmlReader.Create(new MemoryStream(content));

当然,这样做你会发现内容的任何变化,即使是最微小的。

我认为最好的方法是加载feed并只对文章的内容进行哈希,你可以像这样对任何字符串进行哈希:

var toHash = "string to hash";
var hash = MD5.Create().ComputeHash(Encoding.UTF8.GetBytes(toHash);
var hashString = Convert.ToBase64String(hash);

哈希方法在这种情况下不起作用,因为一些服务器端缓存不断非常频繁地添加XML注释,即使实际提要从未更改。

对于这个提要,您可以做的一件事是使用HTTP条件请求,要求服务器仅在数据自上次请求以来实际被修改时才向您提供数据。

例如:

你应该有一个全局/成员变量来保存你的提要中最后修改的日期时间

    var lastModified = DateTime.MinValue;

那么每次你发出如下请求

    var request = (HttpWebRequest)WebRequest.Create( "http://www.extremetech.com/feed" );
    request.IfModifiedSince = lastModified; 
    try {
      using ( var response = (HttpWebResponse)request.GetResponse() ) {
        lastModified  = response.LastModified;
        using ( var stream = response.GetResponseStream() ) {
          //*** parsing the stream
          var reader = XmlReader.Create( stream );
          SyndicationFeed feed = SyndicationFeed.Load( reader );
          }
        }
      }
    catch ( WebException e ) {
      var response = (HttpWebResponse)e.Response;
      if ( response.StatusCode != HttpStatusCode.NotModified )
        throw; // rethrow an unexpected web exception
      }