我正在使用iText重新创建Acrobat的标记树功能。
到目前为止,我已设法获得标记结构。
我想弄清楚的最后一件事是如何获得&解码内容流中标签的“标记内容”。
修改:添加目的
这个问题的目的是弄清楚如何使用mcid访问内容流,并解码内容。
编辑2 :添加iText RUPS参考
下面的图片显示了我在树中到达的位置,红线指向MCID,我试图得到它的内容。
编辑3 :添加构建树的当前代码
private void manipulate(PdfDictionary element, ItemCollection items)
{
if (element == null)
{
return;
}
ICollection<PdfName> val = element.KeySet();
PdfObject tagName = element.Get(PdfName.S);
PdfObject elementType = element.Get(PdfName.Type);
string tn = "";
if (tagName != null)
{
tn = ((PdfName)tagName).GetValue();
}
else
{
tn = ((PdfName)elementType).GetValue();
}
TreeViewItem tvI = new TreeViewItem() { Header = tn, IsExpanded = true };
items.Add(tvI);
PdfArray kids = element.GetAsArray(PdfName.K);
if (kids == null)
{
return;
}
for (int i = 0; i < kids.Size(); i++)
{
PdfDictionary child = kids.GetAsDictionary(i); //Code change required here to detect MCID & get content, this line returns null when child is a MCID
manipulate(child, tvI.Items);
}
}
}
编辑4 :原因是重新创建Acrobat的“标记树”功能。
答案 0 :(得分:2)
根据您添加到问题中的标记,我看到您正在添加iText 7. iText 7有一个名为TaggedPdfReaderTool的类。此类可用于将标记PDF文件转换为XML:
FileOutputStream outXml = new FileOutputStream("pdf_content.xml");
TaggedPdfReaderTool tool = new TaggedPdfReaderTool(document);
tool.setRootTag("root");
tool.convertToXml(outXml);
outXml.close();
XML将具有与您已经能够提取的“标记结构”相同的结构。 XML标记内的内容将与PDF内容流中标记为“标记的一部分”的内容相对应。
向其他读者发送重要信息:问题中的屏幕截图清楚地显示PDF已标记。如果您在未标记的PDF上尝试此代码段,则无法将内容转换为PDF。
更新:较低级别的方法
您还可以检查结构树的所有部分,如下所示:process(document.getStructTreeRoot());
process()
方法如下所示:
public static void process(IPdfStructElem elem) {
if (elem == null) return;
System.out.println(elem.getRole());
System.out.println(elem.getClass().getName());
if (elem instanceof PdfStructElem) {
processStructElem((PdfStructElem) elem);
}
if (elem.getKids() == null) return;
for (IPdfStructElem structElem : elem.getKids()) {
process(structElem);
}
}
public static void processStructElem(PdfStructElem elem) {
PdfDictionary page = elem.getPdfObject().getAsDictionary(PdfName.Pg);
if (page == null) return;
PdfStream contents = page.getAsStream(PdfName.Contents);
if (contents != null) {
System.out.println(new String(contents.getBytes()));
}
PdfArray array = page.getAsArray(PdfName.Contents);
System.out.println(array);
}
请注意,页面的/Contents
可以引用单个流或流数组。在这个简短的片段中,我忽略了存储在数组流中的所有/Contents
。
这是在我们用于测试的标记PDF上执行此操作时显示的内容示例:
EMC
/Artifact BMC
q
0.01961 0.33333 0.52941 rg
36 432.34 184.23 27.98 re
f
Q
EMC
/Span <</MCID 13>> BDC
q
BT
/F2 12 Tf
42 442.65 Td
1 1 1 rg
(The Library)Tj
ET
Q
EMC
/Artifact BMC
q
0.01961 0.33333 0.52941 rg
36 399.11 184.23 27.98 re
f
Q
EMC
/Span <</MCID 14>> BDC
q
BT
/F2 12 Tf
42 409.42 Td
1 1 1 rg
(The Company)Tj
ET
Q
EMC
/Span <</MCID 15>> BDC
q
BT
/F1 20 Tf
227.73 472.71 Td
(The Library)Tj
ET
Q
EMC
/Span <</MCID 16>> BDC
q
BT
/F2 12 Tf
229.23 440.45 Td
(iText is a software developer toolkit that allows users to integrate PDF)Tj
( )Tj
ET
Q
EMC
/Span <</MCID 17>> BDC
q
BT
/F2 12 Tf
229.23 424.46 Td
(functionalities within their applications, processes or products.)Tj
ET
Q
EMC
/Artifact BMC
q
0.01961 0.33333 0.52941 rg
605.03 262.75 191.73 235.31 re
f
Q
EMC
/Span <</MCID 18>> BDC
q
BT
/F1 16 Tf
676.45 482.5 Td
0.97647 0.76078 0.15294 rg
(What?)Tj
ET
Q
EMC
/Span <</MCID 19>> BDC
q
BT
/F2 12 Tf
607.94 453.08 Td
1 1 1 rg
(iText is a software developer toolkit)Tj
( )Tj
ET
Q
EMC
/Span <</MCID 20>> BDC
q
BT
/F2 12 Tf
611.61 437.09 Td
1 1 1 rg
(that allows users to integrate PDF)Tj
( )Tj
ET
Q
EMC
/Span <</MCID 21>> BDC
q
BT
/F2 12 Tf
634.95 421.11 Td
1 1 1 rg
(functionalities within their)Tj
( )Tj
ET
Q
EMC
/Span <</MCID 22>> BDC
q
BT
/F2 12 Tf
669.96 405.12 Td
1 1 1 rg
(applications)Tj
ET
Q
EMC
/Span <</MCID 23>> BDC
q
BT
/F1 16 Tf
679.12 381.5 Td
0.97647 0.76078 0.15294 rg
(How?)Tj
ET
Q
EMC
/Span <</MCID 24>> BDC
q
BT
/F2 12 Tf
613.94 352.08 Td
1 1 1 rg
(By providing you with the tools to)Tj
( )Tj
ET
Q
EMC
/Span <</MCID 25>> BDC
q
BT
/F2 12 Tf
607.59 336.09 Td
1 1 1 rg
(create and manipulate a pdf in your)Tj
( )Tj
ET
Q
EMC
/Span <</MCID 26>> BDC
q
BT
/F2 12 Tf
668.96 320.11 Td
1 1 1 rg
(source code)Tj
ET
Q
EMC
/Span <</MCID 27>> BDC
q
BT
/F1 16 Tf
672.44 296.49 Td
0.97647 0.76078 0.15294 rg
(Really?)Tj
ET
Q
EMC
/Span <</MCID 28>> BDC
q
BT
/F2 12 Tf
673.64 267.06 Td
1 1 1 rg
(Yes really!)Tj
ET
Q
EMC
未标记BMC
/ EDC
或BDC
/ EDC
运算符之间的所有内容。您正在寻找标有MCID的内容。
在评论中,我解释说使用不同的方法会更好。最好解析每个页面的内容流(只有一次),并将遇到的所有对象映射到结构树中的元素。
使用您的方法,您必须为每个结构元素一遍又一遍地解析页面的内容流。这需要更多的处理。