在 C# 中从 itext.layout.element 中提取属性
Attribute extraction from itext.layout.element in c#
目前,我正在开展一个项目,使用 itext 为 pdf 生成 Table 内容我拥有的是一个元素列表 (itext.layout.Element objects)。
我创建了一个字典 用于存储(章节标题和起始页码)。我想考虑
<p class="Heading2ANOC" >
Class 为 Heading2ANOC 的段落是章节标题
我的代码:
var toc = new Dictionary<string,int>();
foreach (IElement element in elements)
{
Console.WriteLine(element.GetType().Name);
if (element.GetType().Name == "HtmlPageBreak")
{
continue;
}
else if (element.GetType().Name == "Paragraph")//need a method to check wheather the class is "Heading2ANOC" {
int count=pdf.GetNumberOfPages();
toc.Add("section" + i, count);//
i++;
}
document.Add((IBlockElement)element);
}
我正在使用以下代码获取元素:
string path = "path for the Html";
string html = File.ReadAllText(path);
IList<IElement> elements = HtmlConverter.ConvertToElements(html);
示例 Html 元素:
<div style="mso-element: para-border-div; border: solid #A6A6A6 2.25pt; padding: 3.0pt 4.0pt 3.0pt 4.0pt; background: #D9D9D9;">
<p class="Heading2ANOC"><span style="mso-bookmark: _Toc190800487;"><span style="mso-bookmark: _Toc377720650;"><span style="mso-bookmark: _Toc396995390;"><span style="font-size: 11.0pt; font-family: 'Open Sans',sans-serif; color: black; mso-color-alt: windowtext;">SECTION 1 <span style="mso-tab-count: 1;"> </span>Name of the section</span></span></span></span></p>
</div>
与您现在采用的方法相比,有一种更简洁(也更灵活)的方法来处理任务,但它需要编写更多代码。幸运的是,代码非常基础。
要了解需要自定义的内容,您需要稍微了解一下 pdfHTML 的工作原理。粗略的说就是按DFS顺序遍历DOM树,将DOM树转化为元素树。每个标签都由标签工作者遍历,标签工作者生成一个元素作为结果。这些元素足够灵活,可以包含任何自定义属性(只要您使用 iText 未使用的唯一 属性 ID),因此您可以在标记工作器中设置这些属性并在以后使用它们。在这种情况下,您想传递 class
property/attribute.
首先,让我们创建一个派生自 PTagWorker
的自定义标签工作者,它将处理 HTML 中的所有段落并设置一个自定义 属性:
public static readonly int CUSTOM_PROPERTY_ID = -10;
private class CustomPTagWorker : PTagWorker {
public CustomPTagWorker(IElementNode element, ProcessorContext context) : base(element, context) {
}
public override void ProcessEnd(IElementNode element, ProcessorContext context) {
base.ProcessEnd(element, context);
IPropertyContainer elementResult = GetElementResult();
if (elementResult != null && !String.IsNullOrEmpty(element.GetAttribute(AttributeConstants.CLASS))) {
elementResult.SetProperty(CUSTOM_PROPERTY_ID, element.GetAttribute(AttributeConstants.CLASS));
}
}
}
然后我们需要以某种方式使用该标签工作者 - 为此我们创建了一个自定义标签工作者工厂:
private class CustomTagWorkerFactory : DefaultTagWorkerFactory {
public override ITagWorker GetCustomTagWorker(IElementNode tag, ProcessorContext context) {
if (TagConstants.P.Equals(tag.Name().ToLower())) {
return new CustomPTagWorker(tag, context);
}
return base.GetCustomTagWorker(tag, context);
}
}
我们现在需要做的就是让 pdfHTML 通过在转换器属性中传递自定义标签工作者来了解这些自定义:
ConverterProperties properties = new ConverterProperties().SetTagWorkerFactory(new CustomTagWorkerFactory());
为了测试它,我们可以遍历元素并检查是否存在我们的自定义 属性(而不是检查 类 的名称):
String html = "<p class=\"Heading2ANOC\">hello</p><p>world</p>";
ConverterProperties properties = new ConverterProperties().SetTagWorkerFactory(new CustomTagWorkerFactory());
IList<IElement> elements = HtmlConverter.ConvertToElements(html, properties);
foreach (IElement element in elements)
{
if (element.HasProperty(CUSTOM_PROPERTY_ID)) {
String propertyValue = element.GetProperty<String>(CUSTOM_PROPERTY_ID);
Console.WriteLine(propertyValue);
}
}
请记住,对于元素相互嵌套的更复杂 HTML,您可能希望以不同的方式执行最终分析,例如
foreach (IElement element in elements)
{
if (element is AbstractElement<Div>) {
var children = (element as AbstractElement<Div>).GetChildren();
// analyze children
}
}
目前,我正在开展一个项目,使用 itext 为 pdf 生成 Table 内容我拥有的是一个元素列表 (itext.layout.Element objects)。
我创建了一个字典
<p class="Heading2ANOC" >
Class 为 Heading2ANOC 的段落是章节标题
我的代码:
var toc = new Dictionary<string,int>();
foreach (IElement element in elements)
{
Console.WriteLine(element.GetType().Name);
if (element.GetType().Name == "HtmlPageBreak")
{
continue;
}
else if (element.GetType().Name == "Paragraph")//need a method to check wheather the class is "Heading2ANOC" {
int count=pdf.GetNumberOfPages();
toc.Add("section" + i, count);//
i++;
}
document.Add((IBlockElement)element);
}
我正在使用以下代码获取元素:
string path = "path for the Html";
string html = File.ReadAllText(path);
IList<IElement> elements = HtmlConverter.ConvertToElements(html);
示例 Html 元素:
<div style="mso-element: para-border-div; border: solid #A6A6A6 2.25pt; padding: 3.0pt 4.0pt 3.0pt 4.0pt; background: #D9D9D9;">
<p class="Heading2ANOC"><span style="mso-bookmark: _Toc190800487;"><span style="mso-bookmark: _Toc377720650;"><span style="mso-bookmark: _Toc396995390;"><span style="font-size: 11.0pt; font-family: 'Open Sans',sans-serif; color: black; mso-color-alt: windowtext;">SECTION 1 <span style="mso-tab-count: 1;"> </span>Name of the section</span></span></span></span></p>
</div>
与您现在采用的方法相比,有一种更简洁(也更灵活)的方法来处理任务,但它需要编写更多代码。幸运的是,代码非常基础。
要了解需要自定义的内容,您需要稍微了解一下 pdfHTML 的工作原理。粗略的说就是按DFS顺序遍历DOM树,将DOM树转化为元素树。每个标签都由标签工作者遍历,标签工作者生成一个元素作为结果。这些元素足够灵活,可以包含任何自定义属性(只要您使用 iText 未使用的唯一 属性 ID),因此您可以在标记工作器中设置这些属性并在以后使用它们。在这种情况下,您想传递 class
property/attribute.
首先,让我们创建一个派生自 PTagWorker
的自定义标签工作者,它将处理 HTML 中的所有段落并设置一个自定义 属性:
public static readonly int CUSTOM_PROPERTY_ID = -10;
private class CustomPTagWorker : PTagWorker {
public CustomPTagWorker(IElementNode element, ProcessorContext context) : base(element, context) {
}
public override void ProcessEnd(IElementNode element, ProcessorContext context) {
base.ProcessEnd(element, context);
IPropertyContainer elementResult = GetElementResult();
if (elementResult != null && !String.IsNullOrEmpty(element.GetAttribute(AttributeConstants.CLASS))) {
elementResult.SetProperty(CUSTOM_PROPERTY_ID, element.GetAttribute(AttributeConstants.CLASS));
}
}
}
然后我们需要以某种方式使用该标签工作者 - 为此我们创建了一个自定义标签工作者工厂:
private class CustomTagWorkerFactory : DefaultTagWorkerFactory {
public override ITagWorker GetCustomTagWorker(IElementNode tag, ProcessorContext context) {
if (TagConstants.P.Equals(tag.Name().ToLower())) {
return new CustomPTagWorker(tag, context);
}
return base.GetCustomTagWorker(tag, context);
}
}
我们现在需要做的就是让 pdfHTML 通过在转换器属性中传递自定义标签工作者来了解这些自定义:
ConverterProperties properties = new ConverterProperties().SetTagWorkerFactory(new CustomTagWorkerFactory());
为了测试它,我们可以遍历元素并检查是否存在我们的自定义 属性(而不是检查 类 的名称):
String html = "<p class=\"Heading2ANOC\">hello</p><p>world</p>";
ConverterProperties properties = new ConverterProperties().SetTagWorkerFactory(new CustomTagWorkerFactory());
IList<IElement> elements = HtmlConverter.ConvertToElements(html, properties);
foreach (IElement element in elements)
{
if (element.HasProperty(CUSTOM_PROPERTY_ID)) {
String propertyValue = element.GetProperty<String>(CUSTOM_PROPERTY_ID);
Console.WriteLine(propertyValue);
}
}
请记住,对于元素相互嵌套的更复杂 HTML,您可能希望以不同的方式执行最终分析,例如
foreach (IElement element in elements)
{
if (element is AbstractElement<Div>) {
var children = (element as AbstractElement<Div>).GetChildren();
// analyze children
}
}