C# iText 7可从HTML访问的PDF:使用display:table时如何避免表标记;
我正在从事一个ASP.NETMVC项目,该项目将视图转换为PDF。以前使用的是Rotavia,但后来一个新的客户要求是PDF可以访问/508兼容。为了便于布局,以前的开发人员将整个标题部分(徽标、标题、免责声明等)作为一个表,没有th元素(仅td)。我需要将它们转换为div,但保持外观不变。因此,我所做的是将它们设为div,然后在适当的地方使用CSS属性display:table、display:table row组、display:table row和display:table cell。结果看起来几乎一模一样 问题是,尽管它们现在是div,但使用iText DefaultTagWorkerFactory的方式如下:C# iText 7可从HTML访问的PDF:使用display:table时如何避免表标记;,c#,css,itext,itext7,html-to-pdf,C#,Css,Itext,Itext7,Html To Pdf,我正在从事一个ASP.NETMVC项目,该项目将视图转换为PDF。以前使用的是Rotavia,但后来一个新的客户要求是PDF可以访问/508兼容。为了便于布局,以前的开发人员将整个标题部分(徽标、标题、免责声明等)作为一个表,没有th元素(仅td)。我需要将它们转换为div,但保持外观不变。因此,我所做的是将它们设为div,然后在适当的地方使用CSS属性display:table、display:table row组、display:table row和display:table cell。结果
ConverterProperties props = new ConverterProperties();
FontProvider fp = new FontProvider();
fp.AddStandardPdfFonts();
props.SetFontProvider(fp);
var tagWorkerFactory = new DefaultTagWorkerFactory();
props.SetTagWorkerFactory(tagWorkerFactory);
HtmlConverter.ConvertToPdf(html, pdfDoc, props);
public class AccessibilityTagWorkerFactory : DefaultTagWorkerFactory
{
public override ITagWorker GetCustomTagWorker(IElementNode tag, ProcessorContext context)
{
var attributes = tag.GetAttributes();
var cssClass = attributes.GetAttribute("class");
if (!string.IsNullOrWhiteSpace(cssClass) && cssClass.Contains("make-div"))
{
return new DivTagWorker(tag, context);
}
return null;
}
}
ITagWorkerFactory customFactory = new DefaultTagWorkerFactory() {
@Override
public ITagWorker getCustomTagWorker(IElementNode tag, ProcessorContext context) {
if (CssConstants.TABLE.equals(tag.getStyles().get(CssConstants.DISPLAY)) && TagConstants.DIV.equals(tag.name())) {
return new DivRoleDisplayTableTagWorker(tag, context);
}
return super.getCustomTagWorker(tag, context);
}
};
它仍然将Div标记转换为table、tr和td标记。显然,在div上使用display:table的全部目的是避免使用表,但获得相同的布局效果
iText为什么要实现这种行为?有什么办法可以解决吗?如果没有,任何人都可以提供display:table、display:table row group、display:table row和display:table cell的精确CSS等价物,因为iText似乎只看到属性“display:table”并使用table标记。我在继承DefaultTagWorkerFactory的自定义标记工作者工厂中尝试了以下操作,在我的div中添加了一个类“make div”,如下所示:
ConverterProperties props = new ConverterProperties();
FontProvider fp = new FontProvider();
fp.AddStandardPdfFonts();
props.SetFontProvider(fp);
var tagWorkerFactory = new DefaultTagWorkerFactory();
props.SetTagWorkerFactory(tagWorkerFactory);
HtmlConverter.ConvertToPdf(html, pdfDoc, props);
public class AccessibilityTagWorkerFactory : DefaultTagWorkerFactory
{
public override ITagWorker GetCustomTagWorker(IElementNode tag, ProcessorContext context)
{
var attributes = tag.GetAttributes();
var cssClass = attributes.GetAttribute("class");
if (!string.IsNullOrWhiteSpace(cssClass) && cssClass.Contains("make-div"))
{
return new DivTagWorker(tag, context);
}
return null;
}
}
ITagWorkerFactory customFactory = new DefaultTagWorkerFactory() {
@Override
public ITagWorker getCustomTagWorker(IElementNode tag, ProcessorContext context) {
if (CssConstants.TABLE.equals(tag.getStyles().get(CssConstants.DISPLAY)) && TagConstants.DIV.equals(tag.name())) {
return new DivRoleDisplayTableTagWorker(tag, context);
}
return super.getCustomTagWorker(tag, context);
}
};
但是,它会抛出一个异常,如“无法隐式地将DivTagWorker转换为DisplayTableRowTagWorker”
我对这一切束手无策。任何帮助都将不胜感激。谢谢。您似乎已将标记辅助程序替换为
显示:表行
元素,但未将标记辅助程序替换为显示:表
。当然我不能确定,因为您还没有共享一个示例HTML文件来重现这个问题
在任何情况下,替代标签工人的方法在这里都不是最好的。它只会删除由自定义显示
CSS属性引起的布局调整,而您的目标是保存布局,但只是更改标记
要保存布局并更改标记,您不应更改创建的标记辅助对象,而应为由这些标记辅助对象创建的表格
和单元格
布局元素设置正确的角色
相应的重载标记工作程序可能如下所示:
private static class DivRoleDisplayTableTagWorker extends DisplayTableTagWorker {
public DivRoleDisplayTableTagWorker(IElementNode element, ProcessorContext context) {
super(element, context);
}
@Override
public void processEnd(IElementNode element, ProcessorContext context) {
super.processEnd(element, context);
if (getElementResult() instanceof Table) {
Table table = (Table) getElementResult();
table.getAccessibilityProperties().setRole(StandardRoles.DIV);
for (int i = 0; i < table.getNumberOfRows(); i++) {
for (int j = 0; j < table.getNumberOfColumns(); j++) {
Cell cell = table.getCell(i, j);
if (cell != null) {
cell.getAccessibilityProperties().setRole(StandardRoles.DIV);
}
}
}
}
}
}
现在,您的表及其单元格将被标记为div。@AlexeySubach发布了一个非常有用的答案。它并没有100%地为我工作,但确实帮助我朝着正确的方向前进。另外,他的答案是Java,我使用的是.NET版本的iText。以下是我最后做的: 我将HTML标记保留为表,因为我有一些表应该是表,而其他表不应该是表(它们只是用于布局),所以我将类“make table div”添加到我不希望成为表的表元素中。然后,我创建了这个类:
public class DivRoleTableTagWorker : TableTagWorker
{
public DivRoleTableTagWorker(IElementNode element, ProcessorContext context) : base(element, context)
{
}
public override void ProcessEnd(IElementNode element, ProcessorContext context)
{
base.ProcessEnd(element, context);
if (GetElementResult().GetType() == typeof(Table))
{
Table table = (Table)GetElementResult();
table.GetAccessibilityProperties().SetRole(StandardRoles.DIV);
for (int i = 0; i < table.GetNumberOfRows(); i++)
{
for (int j = 0; j < table.GetNumberOfColumns(); j++)
{
Cell cell = table.GetCell(i, j);
if (cell != null)
{
cell.GetAccessibilityProperties().SetRole(StandardRoles.DIV);
}
}
}
}
}
}
最后,要使用它:
ConverterProperties props = new ConverterProperties();
FontProvider fp = new FontProvider();
fp.AddStandardPdfFonts();
props.SetFontProvider(fp);
DefaultTagWorkerFactory tagWorkerFactory = new AccessibilityTagWorkerFactory();
props.SetTagWorkerFactory(tagWorkerFactory);
HtmlConverter.ConvertToPdf(html, pdfDoc, props);
pdfDoc.Close();
通过这种方式,我能够保持PDF看起来完全相同,并且仍然有正确的标签。非常感谢您的帮助。Tamer,如果您有此问题的解决方案,请随时通知我。@Fadeel:可以。。。到目前为止看起来不太好though@Fadeel,回答了!非常感谢你。我会尽快试试这个,然后告诉你。谢谢。这真的很有帮助。你也能帮我做这个吗?非常感谢你。