在Java中,您可以传递类似“zip:zip_file!xml_file”的URL,它将使用zip文件中指定的XML文件.XmlUrlResolver没有此功能。有没有办法做到这一点?
答案 0 :(得分:4)
有一个开源解决方案。 (xml reports处的XmlZipResolver代码。)它继承自XmlUrlResolver以添加此功能。
实际上这很简单。 XmlZipResolver类继承自XmlUrlResolver。因此,在创建XmlUrlResolver对象以访问XML文件之前,您可以创建一个XmlZipResolver对象,然后可以像处理XmlUrlResolver对象一样对待它。这适用于XmlUrlResolver只有在url以zip:或jar:(Java jar文件是zip文件)开头时才使用附加代码处理的任何URL。
关键部分是调用GetEntity,它将打开zip文件,然后获取zip文件中所请求的xml文件的流。此代码使用SharpZipLib进行所有zip文件访问。
在此之后,一切都非常简单,所有对成员函数的调用都从嵌入式xml文件的流中返回。因为GetEntity()返回一个对象,如果它返回一个基本的XmlUrlResolver对象,则不会调用此类中的方法。因此,所有剩余的成员函数都是专门为zip文件的情况编写的。
另一项不是返回的Stream是一个包含三个对象的对象,ZipFile,作为zip文件的Stream,以及作为zip条目的流。此返回的对象继承自Stream。对于除Close()之外的每个调用,它只是将相同的调用传递给zip条目流对象。但是在关闭(因此间接在Dispose上),它会关闭所有三个对象。
再次,xml reports的XmlZipResolver代码。
答案 1 :(得分:4)
以下是我使用ICSharpCode.SharpZipLib的一些代码:
public bool Process()
{
var importFile = new FileInfo("c:\\foo\myzip.zip");
var success = true;
using (var zipStream = new ZipInputStream(importFile.OpenRead()))
{
ZipEntry theEntry;
while ((theEntry = zipStream.GetNextEntry()) != null)
{
var lowerName = theEntry.Name.ToLower();
try
{
if (lowerName.EndsWith(".xml") && !lowerName.StartsWith("__macosx"))
{
var doc = new XmlDocument();
doc.Load(zipStream);
}
}
catch (Exception e)
{
success = false;
Log.Error(string.Format("Error parsing {0} ERROR {1}",lowerName,e.Message));
}
}
}
return success;
}
这将处理zip中的每个xml文件...除了突然出现的愚蠢的Mac OsX元文件:)