从 html 创建 pdf 时,如何隐藏具有特定 class 的图像?
How do I hide images that have a certain class when creating a pdf from html?
在使用 iTextSharp (5.x) 将 html 转换为 pdf 时,我试图隐藏包含特定 class 的图像元素时遇到问题。
我无法访问原始的 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" class.
的任何图片元素
我尝试过的:
- 将 img.img-mobile {display:none} 添加到创建 pdf 时发送的 CSS
- 将 img.img-mobile {width:0;height:0} 添加到 CSS
- 将@media print { img.img-mobile: display:none} 添加到 CSS
- 将@media print { img.img-mobile: width:0;height:0} 添加到 CSS
使用正则表达式查找具有该 classes 的 img 元素,然后循环匹配,将源替换为空源并替换该字符串的原始 html使用新字符串(不幸的是,我的正则表达式没有找到任何匹配项)
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 进来的是一致的,因为工具正在其他地方生成它.所以,当一个用户 "adds an image to that html" 时,它的结构总是相同的,所以正则表达式和替换方法是可以接受的,尽管 CSS 方法会更受欢迎......
即使您是 Regex
专家并且您的输入如前所述是可预测的,解析 HTML 也很困难。更好更简单的方法是使用 tested/proven 解析器,几乎所有编程语言都提供该解析器。对于 .NET,它是 HtmlAgilityPack. If you know a bit of XPath,这与 CSS select 非常相似,它的设置非常简单,select 您要删除的特定节点:
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 片段。
更新,在评论 'approved' 代码后:
啊,可怕的 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 并非 如上所述。
在使用 iTextSharp (5.x) 将 html 转换为 pdf 时,我试图隐藏包含特定 class 的图像元素时遇到问题。
我无法访问原始的 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" class.
的任何图片元素我尝试过的:
- 将 img.img-mobile {display:none} 添加到创建 pdf 时发送的 CSS
- 将 img.img-mobile {width:0;height:0} 添加到 CSS
- 将@media print { img.img-mobile: display:none} 添加到 CSS
- 将@media print { img.img-mobile: width:0;height:0} 添加到 CSS
使用正则表达式查找具有该 classes 的 img 元素,然后循环匹配,将源替换为空源并替换该字符串的原始 html使用新字符串(不幸的是,我的正则表达式没有找到任何匹配项)
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 进来的是一致的,因为工具正在其他地方生成它.所以,当一个用户 "adds an image to that html" 时,它的结构总是相同的,所以正则表达式和替换方法是可以接受的,尽管 CSS 方法会更受欢迎......
即使您是 Regex
专家并且您的输入如前所述是可预测的,解析 HTML 也很困难。更好更简单的方法是使用 tested/proven 解析器,几乎所有编程语言都提供该解析器。对于 .NET,它是 HtmlAgilityPack. If you know a bit of XPath,这与 CSS select 非常相似,它的设置非常简单,select 您要删除的特定节点:
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 片段。
更新,在评论 'approved' 代码后:
啊,可怕的 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 并非 如上所述。