使用iTextSharp(5.x)将html转换为pdf时,我在尝试隐藏包含某个类的图像元素时出现问题。
我没有访问原始Html,因为它来自另一个来源,但是,我可以在C#之后做一些基本的东西,比如Regex和string.replace。
Html字符串的一个简单示例如下:
<div>
<div>
<img src="somepath/desktop.jpg" class="img-desktop">Desktop</img>
<img src="somepath/mobile.jpg" class="img-mobile">Mobile</img>
</div>
</div>
然后使用iTextSharp中的XMLWorker将此字符串创建为PDF。
我需要隐藏第二张图片,更常见的是隐藏任何带有“img-mobile”类的图像元素。
我尝试了什么:
使用Regex查找包含该类的img元素,然后循环匹配,用空源替换源,并用新字符串替换该字符串的原始html(我的Regex没有抓取任何匹配,不幸的是)
var pattern = "<img.*?class=\"img-mobile.*\"\\s?>.*</img>";
var mobileImages = Regex.Matches(innerHtml, pattern);
var srcPattern = "src=\".*\" ";
foreach (var imageElement in mobileImages)
{
var replaceString = Regex.Replace(imageElement.ToString(), srcPattern, " ");
innerHtml.Replace(imageElement.ToString(), replaceString);
}
我很快就没有关于如何处理这个问题的想法...唯一的优点是,由于工具在其他地方生成它,所以进入的Html是一致的。因此,当用户“将图像添加到该html”时,它的结构将始终相同,因此可以接受正则表达式和替换方法,尽管CSS方法会更受欢迎...
答案 0 :(得分:1)
即使您是Regex
专家,并且您的输入是可预测的,如上所述,解析HTML很难。更好,更简单的方法是使用经过测试/验证的解析器,几乎可以在每种编程语言中使用。对于.NET,它是HtmlAgilityPack。如果您知道一些XPath,它与CSS选择器非常相似,那么设置和选择要删除的特定节点非常简单:
string RemoveImage(string htmlToParse)
{
var hDocument = new HtmlDocument()
{
OptionWriteEmptyNodes = true,
OptionAutoCloseOnEnd = true
};
hDocument.LoadHtml(htmlToParse);
var root = hDocument.DocumentNode;
var imagesDesktop = root.SelectNodes("//img[@class='img-desktop']");
foreach (var image in imagesDesktop)
{
var imageText = image.NextSibling;
imageText.Remove();
image.Remove();
}
return root.WriteTo();
}
然后将解析后的HTML传递给iTextSharp:
var parsedHtml = RemoveImage(HTML);
using (var xmlSnippet = new StringReader(parsedHtml))
{
using (FileStream stream = new FileStream(
outputFile,
FileMode.Create,
FileAccess.Write))
{
using (var document = new Document())
{
PdfWriter writer = PdfWriter.GetInstance(
document, stream
);
document.Open();
XMLWorkerHelper.GetInstance().ParseXHtml(
writer, document, xmlSnippet
);
}
}
}
使用您提供的HTML代码段为我工作。
在对“已批准”代码发表评论之后更新:
Aah,可怕的CCB。知道这是怎么回事。 :(如果HtmlAgilityPack
没有通过,这里是一个替代解决方案,虽然它可能不是最好的Regex
写的。;)
const string HTML = @"
<div>
<p class='img-desktop'>Paragraph</p>
<div>
<img src='somepath/desktop.jpg' class='img-desktop'>Desktop</img>
<img src='somepath/mobile.jpg' class='img-mobile'>Mobile</img>
</div>
<div>
<img src='somepath/desktop.jpg' alt='img-desktop' title='img-desktop' class=""img-desktop"">Desktop
</IMG>
<img src='somepath/mobile.jpg' class='img-mobile'>Mobile</img>
</div>
</div>";
public void Go()
{
var regex = new Regex(
// initial update
// @"<img[^>]*class='?""?'?img-desktop""?[^>]*>.*?</img>",
// after seeing accepted answer, noticed a bad copy/paste.
// above works, but for readability should have been this:
@"<img[^>]*class='?""?img-desktop""?'?[^>]*>.*?</img>",
// and also noticed above can be shortened to this, which works too
// @"<img[^>]*class=[^>]*img-desktop[^>]*>.*?</img>"
RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.Singleline
);
Console.WriteLine(regex.Replace(HTML, ""));
}
Regex
为您提供小额外余地,以防您正在处理的实际HTML不是完全,如上所述。