使用MCID内容

时间:2017-07-18 05:08:45

标签: pdf itext7

我正在使用iText重新创建Acrobat的标记树功能。

到目前为止,我已设法获得标记结构。

我想弄清楚的最后一件事是如何获得&解码内容流中标签的“标记内容”。

enter image description here

修改:添加目的

这个问题的目的是弄清楚如何使用mcid访问内容流,并解码内容。

编辑2 :添加iText RUPS参考

下面的图片显示了我在树中到达的位置,红线指向MCID,我试图得到它的内容。

enter image description here

编辑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的“标记树”功能。

1 个答案:

答案 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 / EDCBDC / EDC运算符之间的所有内容。您正在寻找标有MCID的内容。

在评论中,我解释说使用不同的方法会更好。最好解析每个页面的内容流(只有一次),并将遇到的所有对象映射到结构树中的元素。

使用您的方法,您必须为每个结构元素一遍又一遍地解析页面的内容流。这需要更多的处理。