首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >iTextSharp XMLWorker不读取<link> CSS标记

iTextSharp XMLWorker不读取<link> CSS标记
EN

Stack Overflow用户
提问于 2015-12-31 17:48:35
回答 1查看 1.1K关注 0票数 0

所以我一直在绞尽脑汁想这个。以下代码如下:

代码语言:javascript
复制
string content = ConvertHTMLToXHTML(content); //This is something I wrote
var doc = new iTextSharp.text.Document(PageSize.LETTER, 10f, 10f, 10f, 0f);
var writer = PdfWriter.GetInstance(doc, ms);                
doc.Open();

ICSSResolver cssResolver = null;
cssResolver = XMLWorkerHelper.GetInstance().GetDefaultCssResolver(false);
cssResolver.AddCss(@"code { padding: 2px 4px; }", "utf-8", true);

//****This is the key line******
cssResolver.AddCssFile(@"<the css file>", true);

var hpc = new HtmlPipelineContext(new CssAppliersImpl(new XMLWorkerFontProvider()));
hpc.SetAcceptUnknown(true).AutoBookmark(true).SetTagFactory(tagProcessors); // inject the tagProcessors
hpc.SetLinkProvider(new LinkProvider(currentWorkingDirectory));

var htmlPipeline = new HtmlPipeline(hpc, new PdfWriterPipeline(doc, writer));

var pipeline = new CssResolverPipeline(cssResolver, htmlPipeline);

var worker = new XMLWorker(pipeline, true);
var xmlParser = new XMLParser(true, worker, Encoding.UTF8);

//Ok, now we can finally parse all this
using (var srHtml = new StringReader(content)) {
    xmlParser.Parse(srHtml);
}

doc.Close();

注意我写“这是关键行”的那一行。这就是我用来调试的东西。

因此,在内容中,我有在<link href='[valid address]' rel="stylesheet" />标记中设置的有效<head>。预处理风格中,我确保使用我的方法ConvertHTMLtoXHTML将内容解析为完全解析href(它使用HTMLAgilityPack,并验证内容已经完全解析了URL)。示例完全解析的url类似于http://localhost/foo/bar.css

但是,内容不与CSS一起呈现。因此,我转到AddCssFile (请参阅这是键行),并试图通过URI路径将文件添加到那里(这都在我的系统上,所以我使用的是'http://localhost/foo/bar/blah.css')。这引发了一个异常,因为它无法找到文件(异常是System.IO.IOException: retrieve.file.from.nothing)。

然后,我通过AddCssFile (例如: D:\foo\bar\blah.css)将文件添加到我的文件系统中,因此它工作了!!

我的问题是,是否有一种方法可以让XMLWorker读取链接标记(如果我已经完全解决了它们),而不是我必须找到所有链接标记,将它们转换到位于磁盘上的位置,然后通过CSSResolver添加链接标记?

其他信息:

  • ASP.Net MVC 4
  • iTextSharp 5.5.8
  • iTextSharp.xmlworker 5.5.8
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-12-31 22:36:33

确定了一个解决方案--必须深入研究iTextSharp的源代码,因为我正在使用已编译的DLL,而异常消息并不是完全有用的。

顺便说一句,这是两个部分。

获取CSS时需要进行身份验证

我的网站只允许经过认证的用户使用该网站。因此,当iTextSharp在FileRetrieveImpl中生成WebRequest时,它发出了一个简单的未经身份验证的GET请求。然后,请求失败了,一个401 -未经授权,这反过来抛出了一个retrieve.file.from.nothing异常从iTextSharp。

为了解决这个问题,我需要使用以下代码

代码语言:javascript
复制
WebRequest w = WebRequest.Create(url);
w.UseDefaultCredentials = true;
w.PreAuthenticate = true;
w.Credentials = CredentialCache.DefaultCredentials;

在提出请求之前。因此,我需要在我使用的FileRetrieve解析器上重写ICSSResolver。我决定需要FileRetrieveImpl的当前实现,同时重写方法ProcessFromHref,这给我带来了痛苦。

因此,我编写了下面的代码,复制并粘贴了我从FileRetrieveImpl中需要的项目。

代码语言:javascript
复制
private class CustomFileRetriever : FileRetrieveImpl {
    private static ILogger LOGGER = LoggerFactory.GetLogger(typeof(FileRetrieveImpl));
    private IList<string> rootdirs;
    private IList<string> urls;

    public CustomFileRetriever() {
        rootdirs = new List<string>();
        urls = new List<string>();
    }

    private Uri DetectWithRootUrls(string href) {
        foreach (string root in urls) {
            try {
                return new Uri(root + href);
            } catch (UriFormatException) {
            }
        }
        throw new UriFormatException();
    }

    public override void ProcessFromHref(string href, IReadingProcessor processor) {
        if (LOGGER.IsLogging(Level.DEBUG)) {
            LOGGER.Debug(string.Format(LocaleMessages.GetInstance().GetMessage("retrieve.file.from"), href));
        }
        Uri url = null;
        bool isfile = false;
        string f = href;
        try {
            url = new Uri(href);
        } catch (UriFormatException) {
            try {
                url = DetectWithRootUrls(href);
            } catch (UriFormatException) {
                // its probably a file, try to detect it.
                isfile = true;
                if (!(File.Exists(href))) {
                    isfile = false;
                    foreach (string root in rootdirs) {
                        f = Path.Combine(root, href);
                        if (File.Exists(f)) {
                            isfile = true;
                            break;
                        }
                    }
                }
            }
        }

        Stream inp = null;

        if (null != url) {

            //***********************
            //Begin changed part
            //***********************
            WebRequest w = WebRequest.Create(url);
            w.UseDefaultCredentials = true;
            w.PreAuthenticate = true;
            w.Credentials = CredentialCache.DefaultCredentials;
            //***********************
            //End changed part
            //***********************

            try {
                inp = w.GetResponse().GetResponseStream();
            } catch (WebException) {
                throw new IOException(LocaleMessages.GetInstance().GetMessage("retrieve.file.from.nothing"));
            }
        } else if (isfile) {
            inp = new FileStream(f, FileMode.Open, FileAccess.Read, FileShare.Read);
        } else {
            throw new IOException(LocaleMessages.GetInstance().GetMessage("retrieve.file.from.nothing"));
        }
        Read(processor, inp);
    }

    private void Read(IReadingProcessor processor, Stream inp) {
        try {
            int inbit = -1;
            while ((inbit = inp.ReadByte()) != -1) {
                processor.Process(inbit);
            }
        } catch (IOException e) {
            throw e;
        } finally {
            try {
                if (null != inp) {
                    inp.Close();
                }
            } catch (IOException e) {
                throw new RuntimeWorkerException(e);
            }
        }
    }
}

然后,我简单地重写了默认的文件检索器。

代码语言:javascript
复制
ICSSResolver cssResolver = XMLWorkerHelper.GetInstance().GetDefaultCssResolver(false);
cssResolver.FileRetrieve = new CustomFileRetriever();

这解决了我打电话给AddCssFile和获取retrieve.file.from.nothing的问题。但是,我不只是想调用AddCssFile,我想让iTextSharp识别链接。因此,这就引出了下一部分。

HTML中的链接标记需要特定的属性

在我的问题陈述中,我写了它是如何没有得到<link href='[valid address]' rel="stylesheet" />的。这是因为它缺少属性标记type="text/css"。因此,我应该有<link href='[valid address]' rel="stylesheet" type="text/css"/>

我通过阅读源代码来识别这一点(请参阅链接)。在处理XHTML标记时,它会看到标记完全存在并完全解析。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/34549881

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档