close

Вход

Забыли?

вход по аккаунту

Поляков Кирилл Павлович. Разработка и реализация программного обеспечения для автоматической генерации индексных файлов изданий для электронной библиотеки

код для вставки
fiCrcOfi OEAEP AI-JJIU
yTIPEXAEHI4E
oEAEPAJIbHOE f OCyAAPCTBEHHOE EIOAXETHOE OBPA3OBATEJIbHOE
MI4HI4
C TE,P C
TB
o o E P 43 o B AH vyn V HAyKI4
POC
CZ
BbICIIIE| O OEPA3OBAHI4'
<oplo gcxutZ f ocy.{APCTBSHFITUZ yFII4SEPCI4TET
ur'reuu I4.C.
TYPfEHEBA)
BbrrIycKHAt KBAJII4OI4KAIII{OHHA' PAEOTA (MA|}ICTEPCKAT AI4CCEPTAUI4')
11o
HanpaBJreHgro rroAroroBKr4
0
1
.04.02 flprannalHas MareMarI,IKa
14
I4HOopMarrIKa
HanpaBneHHocrb (npoQulr) : MareMarl4rlecKoe MoAenIapoBaHI4e
rxrz$p
Cryleura llorqxoBa KI{p vrJrna flasroeuqa
@
axyn
rrer (uuculryr)
165013
: @ HsI'IKo - MareMarI'IqecKI'Ifi
Pa:pa6orra u pe€rJrr.r3allfit npOrptMMHoIo O6eCne.IeHI'I.t A;1s aBToMar[qecKgfi rcHepaq u uHAeKcHbIx
rpaft
non uraauufi AJII 3JIe(TpoHIrofi 6u6ltorerr'l
Crylenr
florqxos K. ll.
Pyxoeo4l4rerIb
HosuKoe B. C.
Peqeusenr
Prouruun B. B.
3ae. xaQeApofi / POfl
lopo$eeea B.
Oper 201
8
14.
M14HI4CTEPCTBo oEPA3oB AHIAfr 14 HAYKI4 POCCI4iICKOIZ @EAEPAIJVIVI
yL{PEXAEH I4E
EH H O E EIOAX ETHO E OB PA3OBATEJI bHO E
B bICTilETO OB PA3OBAHI4,q
( O p JIO B C Kl1n f O C y AA P C T B E HH blil, V HLAB E P C I,l T ET
I4MeH wVl.C. TYPf EHEBA))
o EAE pAJr b HO E TOCyAA PCTB
arylnrer
0 I43 I4 K o -M areM ar vrqecKr4it'
ItaQ eapa LIH$opMarAKI4
HanpaureHr{e noAroroBKr4 01.04 .02
@
Hanp
aeJr eHHo
crr
(up o S ral
r) Mareu
- llpuxnar*afl, MareMarl4Ka 14 I4H$opMarI4Ka
arl,Iq ecKo e MoAenI4poBaHI4e
YTBEPXAAIO:
3A,ITAHI,IE
Ha BbI[oJIHeHue arrnycxnoft r<nalnQzraqzonuoft pa6otu
cryAenta florrr<ona Kupulna llasrosuqa urra$p 165013 .
O6eCneqeHuff AJrs
1 . Telra BKP Paspa6oTKa rr peaJrr{3arlrrfl nporpaMMHoro
aBToMaT[qecrcofi reHepaquu IIHAeKcHbrx Qafi.non usAaHufi 4.na e.nexrponnofi
6u6,r uorenn
Yraepx4ena nplrKa3oM no yHl,IBepcl{rery or <10> uor6pa 2017 roaa Ns 2-3227
2.Cpox cAaqI,I cryAeHroM 3aroHqeunoft pa6oru <13> uronq 2018 roaa
3.ZcxoAHbre AaHHbre x pa6ore: TexHr4qecKafl AoKyMeHTaIII4s, orll4caH:/^fl, $opir,raron.
4.Co4epNanr.re BKP
Aunoraqus
BseAeHue
fnaea
1.
lloctanonra
3aAaqu
1.1 flocraHoeKa 3araqu
1.2 06ocrrosauue nrt6opa I,IHcrpyMeHra peaJIIl3aII[lI
gJIeMeHroB pa3MeTKI4 B
1.3 Ilorzcr u o6ocuosaHlle Kp[TepLIeB BbIAeJIeHLIf cTpyKTypHbIx
PDF-Qafi.ne c IIeJILIo flepeuoca zHtpopn'raqr'rr'r 143 Hzx B Qaftmt pasMerKl4
snertpounoft 6u6lraotexu
1.4 Pao6op crpyKrypbl Qoprrra'ra tpe6yeuoro SAP-Qafua
I
rasa 2. llporparurunaa pe€uIIt3al{Irt
J
Pazpa6orxa MoAynfl BbIAeIeHI,Iq sJIeMeHroB PDF-AoKyMeHra
2 .2 P trgp a5 orr<a MoAynr s opM r4po Ba HVs, $afi,m xML
2.3 lhpueMbl rteKcur{ecKoro aHaIIvI3a reKcra XML-Safua
2 .4 P aspa6 orxa MoAyru Q opMprpoBa HVn. safi rra s AP
2.I
|IABA
3
.
IIPAKTI4qECKOE I'ICIOIb3OBAHI4E
3arruoqeHI4e
Cnucox nl4reparypbl
flpv noNeHHe
5.
llepeqeHb rpa$r'ruecKoro Marepl4ana
Pucyuxos - 6
6. KoncvjrbraHrbr rro BKP (c yr<asaHr4eM orHocflIrll4xcs K HLIM pa3AerG
floAuucb, p.ara
KoucylbraHr
PasAer
3arauue rpuHfln
3alalg^ue BbIAan
Aara BbIAaqu 3aralkrfl' (10) ruox6pt,2017
HayvHrrfi pyxoBoAl4rell BKP
3aAaune npI4HflJI K HctloJIHeIlHIo
r'
Hoeuros B.C.
llorqxoe K.ll.
KAIEHAAP
Cporc BrIIIoJIH eHvrr,
HauueHoBaHHe 3Ta[oB
BKP
flo46op v
aHalrvr3 I4crorrHHKoB
HayqHbIX I43AaHkrv
n nIAH
w
orarloB pa6oru
uor6pr-4exa6ps 2017
llprarueqaHHe
BunolHeHo
ilo
HanncaHI4e BBeAeHI4q
HanncaHne rrtaslt I
HanrzcaHne rrIaBbI 2u3
Hann caHl4e 3aKJIroq eHvrfl'
OrhonvreHI,Ie BKP
Cnaqa BKP
CryAenr
Hayuustil pyxoBoAl4renb BKP
nrafi 201 8 r.
rHBapb-Senpans 201 8 r.
Mapr-anpenb 2018 r.
nrafi 201 8 r.
r,rroHb 201 8 r.
r4roJlb 201 8 r.
BunolHeHo
BrrnolHeHo
BsrnonHeHo
BunolHeHo
BltnolHeHo
BrtuolHeHo
llolsxoe K.lI.
HoeuKoe B.C.
Аннотация
Магистерская диссертация на тему «Разработка и реализация программного
обеспечения для автоматической генерации индексных файлов изданий для
электронной библиотеки» содержит 72 страницы текста, рисунков – 6,
использованных источников - 8.
В настоящее время подобные задачи востребованы по причине увеличивающейся
необходимости автоматизации процесса анализа и преобразования крупных
объѐмов библиографической информации.
Ключевые слова: сборник научных работ, электронная библиотека, программная
автоматизация, программное обеспечение.
Предмет
исследования.
Содержание
программного
обеспечения
для
автоматизации процесса анализа и преобразования файлов сборников научных
работ и возможности его применения для исследования задачи.
Объект исследования. Алгоритмы и инструменты для обработки текста и
дальнейшего выделения из него необходимой информации.
Цель работы. Создание программного обеспечения для выделения и извлечения
структурных элементов текста из XML-файла и формирования файлов разметки
*.SAP для электронной библиотеки eLibrary.
Метод исследования. Для исследования применяется метод обратной разработки
(реверс-инжиниринг).
Результаты работы. В магистерской диссертации разработана программа на
языке программирования Java [1], позволяющая решить задачу распознавания
структурных элементов сборника научных трудов с целью автоматической
генерации файла разметки для публикации в электронном каталоге, выполнена
апробация на тестовых задачах.
2
Работа имеет теоретическое и практическое значение, т.к. разработанное
программное обеспечение может применяться для дальнейших исследований при
различных входных параметрах исходных файлов и решения подобных задач
прикладного характера.
3
Abstract
Master's thesis on "Development and implementation of software for automatic
generation of index files for electronic library" contains 72 pages of text, pictures - 6,
sources used - 8.
Now, such tasks are in demand due to the increasing need to automate the process of
analyzing and converting large volumes of binary information.
Keywords: collection of scientific works, electronic library, software automation,
software.
The subject of the study. The contents of the software for the automation of the process
of analyzing and converting files of collections of scientific papers and the possibilities
of its application for the study of the problem.
The object of study. Algorithms and tools for processing text and further extracting
necessary information from it.
The purpose of the work. Research of the problem and development of software for
automation of the process of analysis and transformation of large volumes of binary
information of scientific research collections for the purpose of further publication in
the electronic catalog using reverse engineering methods.
Method of the study. For the study applies the method of reverse engineering.
The results of the work. In master's thesis developed a program in Java [1] that allows to
solve the problem of converting large volumes of binary information from collections of
scientific papers for the purpose of further publication in the electronic catalog,
performed testing of arbitrary tasks.
The work has theoretical and practical importance, because the developed software can
be used for further research with various input parameters of source files and solving
applied problems related to similar solved ones.
4
СОДЕРЖАНИЕ
ВВЕДЕНИЕ…………………………………………………….………………..….....8
ГЛАВА 1. ПОСТАНОВКА ЗАДАЧИ……………….……….………………….…..12
1.1 Постановка задачи..10
1.2 Обоснование выбора инструмента реализации…………………..….12
1.3 Поиск и обоснование критериев выделения структурных элементов
разметки в PDF-файле с целью переноса информации из них в файлы
разметки электронной библиотеки………………………………..…..13
1.4 Разбор структуры формата требуемого SAP-файла………………….17
ГЛАВА 2. ПРОГРАММНАЯ РЕАЛИЗАЦИЯ……………………………………....19
2.1 Разработка модуля выделения элементов PDF-документа…………...…19
2.2 Разработка модуля формирования файла XML……………….………….24
2.3 Приемы лексического анализа текста XML-файла…………………...…27
2.4 Разработка модуля формирования файла SAP……………….………..…29
ГЛАВА 3. ПРАКТИЧЕСКОЕ ИСПОЛЬЗОВАНИЕ……………………..………….45
Заключение……………………………………………………………….……………47
Список литературы……………………………………….…………………….……..48
Приложение…………………………………………………………………….……...49
5
ВВЕДЕНИЕ
Обоснование выбора темы и ее актуальность
Отличительной особенностью нынешней стадии развития социума является
то, что информация существует как в привычной печатной, так и в электронной
форме. К тому же актуальные информационные технологии позволили не только
начать
обширный
перевод
накопленной
человечеством
информации
в
электронную форму, но и создание немалого количества новых ресурсов
предоставления информации сразу же в электронном виде. Такая подача
информации помимо значительного ускорения процессов обмена позволяет на
совершенно новом качественном уровне хранить, распространять и производить
информацию.
Обеспечение
предоставления
открытого
информации
доступа
стало
людей
одной
к
из
электронным
ресурсам
первостепенных
задач
информационного обслуживания образования и науки. В данный момент уже не
требуется доказательств то, что предоставление информации, базирующееся всего
лишь на печатных ресурсах устарела, и на еѐ место пришла другая, - основанная
на предоставлении различной информации в электронной форме, неограниченной
в количестве и доступной незамедлительно через всемирные сети передачи
данных вне зависимости от местонахождения пользователя и времени обращения.
Благодаря этому значительно меняются роли и функции такого социального
института, как библиотека - первостепенного места хранения и распространения
информации. Появляются ресурсы, хранящие и предоставляющие доступ
исключительно к материалам в форме электронного представления - так
называемые электронные библиотеки.
Говоря об электронных библиотеках, важно отметить их функцию
предоставления доступа пользователей к цифровым версиям источников
6
информации, ранее имевших вид
печатных изданий,
либо
выходящих
одновременно в виде электронного и физического представления. Появляются
проблемы, связанные с большим объемом работы по оцифровке и каталогизации
информации, появляется необходимость автоматизации связанных с ними
процессов и прикладные задачи их решения.
Актуальность темы определяется насущностью задач семантического
анализа текста, извлечения текста из XML-файлов разметки для библиотеки
eLibrary и последующей генерации файлов *.SAP с целью автоматизации
рутинных и трудоемких процессов каталогизации ассортимента электронных
библиотек и, как следствие, необходимостью максимальной, насколько это
возможно, автоматизации данной работы.
Степень разработанности проблемы
В текущий момент задача, решаемая работой, выполняется вручную с
помощью программного обеспечения, предоставляющего возможность ручного
набора индексного файла разметки издания сборника научных работ с
использованием графического интерфейса.
В данной работе выполняется задача анализа структуры требуемого для
генерации файла и промежуточного файла, требующегося для работы алгоритма с
помощью приѐма обратной разработки (реверс-инжиниринг; англ. reverse
engineering) для дальнейшей реализации автоматизированного программного
продукта.
Также необходимо
уделить
внимание выбору современного
языка
программирования, отвечающего задачам кроссплатформенности и возможности
реализовать нересурсоѐмкую программу. Исходя из данной необходимости был
выбран высокоуровневый язык программирования Java [1] и использован способ
последовательного чтения и записи XML-файлов под названием SAX [3], а также
библиотека pdf2xml [2].
Предмет исследования.
Содержание программного обеспечения для автоматизации процесса анализа и
7
преобразования файлов сборников научных работ и возможности его применения
для исследования задачи.
Объект исследования
Алгоритмы и инструменты для обработки текста и дальнейшего выделения
из него необходимой информации.
Цель работы.
Создание программного обеспечения для
выделения
и извлечения
структурных элементов текста из XML-файла и формирования файлов разметки
*.SAP для электронной библиотеки eLibrary.
Основные задачи исследования:
1. Выбрать и обосновать технологию извлечения текста из файла формата PDF.
2.Определить устойчивые критерии идентификации структурных элементов
документа.
3. Разработать ПО для выделения текста структурных элементов и получения
файлов разметки в формате *.SAP электронной библиотеки eLibrary.
Метод исследования.
Для исследования применяется метод обратной разработки (реверс-инжиниринг).
Структура работы
Во введении обосновывается актуальность решаемой задачи, анализируются
степень разработанности данной проблемы, ставится цель и задачи исследования,
а также основные направления исследования.
В первой главе ставится задача, которая будет исследована, обосновывается
выбор инструмента реализации, производится поиск и обоснование критериев
выделения структурных элементов разметки в PDF-файле с целью переноса
информации из них в файлы разметки электронной библиотеки, происходит
8
разбор байтововой структуры формата требуемого SAP-файла.
Во второй главе описывается программная реализация поставленной задачи:
описываются причины выбора языка программирования Java [1], описываются
процессы разработки модуля выделения элементов PDF-документа, модуля
формирования файла XML [7] и модуля формирования файла SAP,разъясняются
приемы лексического анализа текстовой информации XML-файла.
В третьей главе проводится апробация разработанного программного
обеспечения.
В заключении делается вывод о полученных в ходе исследования результатах
работ и дальнейших перспективах исследования.
Приводится список использованных источников.
В приложении приводится листинг исходного программного кода.
Апробация работы
Промежуточные результаты исследование были обнародованы на заседании
семинара "Вычислительные технологии и их приложения", который проводится
совместно с Академией ФСО в Интернет-центре Орловского Государственного
Университета им. И.С. Тургенева и опубликованы в учебных работах по мере
прохождения обучения.
9
ГЛАВА 1. ПОСТАНОВКА ЗАДАЧИ
1.1 Постановка задачи
Необходимо разработать программный продукт для получения SAP-файла
разметки издания на основе XML-файла для дальнейшего использования в
электронной библиотеке eLibrary.
1.2 Обоснование выбора инструмента реализации
В качестве инструмента реализации конечного программного продукта
выбран типизированный объектно-ориентированный язык программирования Java
[1]. Приложения, разработанные на данном языке, обычно транслируются в
специальный байт-код, поэтому они могут работать на любой компьютерной
архитектуре
преимущество
с
помощью
виртуальной
кроссплатформенности,
Java-машины,
немаловажное
из
для
чего
следует
дальнейшего
применения программы.
Для решения рутинной типовой задачи предварительной обработки PDF для
конвертирования его в формат XML-представления текстового слоя исходного
файла была выбрана утилита pdf2xml [2], основанная на библиотеках iText [4] и
XPdf [6]. Данная утилита проста в настройке и установке на любой операционной
системе.
Выбор
готового
решения
в
данном
случае
обусловлен
целью
сконцентрироваться на решении нетривиальной задачи написания конечного
программного продукта, который будет работать с данным XML [7], полученным
с помощью этой утилиты.
10
1.3 Поиск и обоснование критериев выделения структурных элементов
разметки в PDF-файле с целью переноса информации из них в файлы
разметки электронной библиотеки.
При
анализе
исходного
файла
необходимо
выявить
параметры,
специфичные для каждого текстового блока с целью дальнейшей программной
реализации алгоритма их выделения.
Исходными файлами являются XML-файлы табличного представления,
полученные ранее из ВКР по выделению текстовых блоков PDF-файлов
сборников научных статей Орловского Государственного Университета им. И.С.
Тургенева. Они имеют типовую структуру, вся текстовая информация в них
соответствует стандарту представления
Extensible Markup
Language,
что
позволяет выделить критерии устойчивой идентификации каждого из блоков
текста, например, заголовка статьи, списка ключевых слов или названия самого
сборника и далее обрабатывать средствами семантических алгоритмов данной
работы.
В качестве примера можно привести статью сборника научных работ. При
дальнейшей
реализации
идентификации.
будут
применяться
точно
такие
же
приемы
11
Рисунок 1 – заголовок научной статьи
12
Рисунок 2 - фрагмент текста научной статьи
Стоит отметить, что в правильно составленном файле сборника каждая из
частей логической структуры текста имеет свои уникальные особенности – тип
шрифта и его параметры (размер, жирность, курсив, и так далее). Основываясь на
данной типовой странице, выделим уникальные параметры для блоков текста,
которые в дальнейшем будут указаны в программной реализации:
Номер УДК - жирный текст, шрифт Cambria с засечками (serif), размер шрифта 10 пунктов.
13
ФИО автора статьи: жирный курсив, шрифт Cambria с засечками, размер шрифта 10 пунктов.
Заголовок статьи: жирный текст, шрифт Cambria с засечками, размер шрифта - 10
пунктов.
Аннотация: жирный курсив, шрифт Times New Roman без засечек, размер шрифта
- 10 пунктов.
Ключевые слова: начало блока текста - подчѐркнутый курсив, список - жирный
курсив, шрифт Cambria с засечками, размер шрифта - 10 пунктов.
Текст статьи: шрифт Times New Roman с засечками, размер шрифта - 10 пунктов.
Библиографический список: шрифт Times New Roman с засечками, размер
шрифта - 9 пунктов.
Информация всех полей дублируется на двух языках – русском и
английском.
После анализа исходных данных можно приступать к разработке алгоритма
итоговой реализации.
14
1.4 Разбор структуры формата требуемого SAP-файла.
В электронную библиотеку eLibrary, принимающую сборники научных
статей,
рассматривающихся
в
данной
работе,
издания
поступают
в
специализированном формате .SAP, работа с которым проводилась в предыдущих
курсовых работах.
SAP-файл представляет собой упорядоченную последовательность байт,
имеющую определенную структуру.
В начале любого такого файла имеется заголовок, всегда имеющий один и тот же
вид:
7B 73 61 70 31 7D 10 6A 13 52 55 53 13 39 31 11 12 10
6E 13 30 13 33 13 34 13 30 13
в байтовом представлении, или
{sap1}.j.RUS.91...n.0.3.4.0.
– в текстовом (каждая точка в текстовом представлении – различный байт). Далее
идѐт заголовок первого поля с информацией об издании и специфичный для него
байтовый код:
49 53 53 4E 2F CA EE E4 20 CD DD C1 11 12 10 6E 13 31
13 34 13 31 13 31 13 31 39 39 38 32 37 32 30 11
Или
15
ISSN/Код НЭБ...n.1.4.1.1.19982720.
где «19982720» – значение поля «ISSN/Код НЭБ».
Следующим в файле находится фрагмент с форматом, подобным файлу RTF с
некоторыми добавлениями SAP:
7B 5C 72 74 66 31 5C 61 6E 73 69 5C 61 6E 73 69 63 70
67 31 32 35 31 5C 64 65 66 66 30 5C 64 65 66 6C 61 6E
67 31 30 34 39 7B 5C 66 6F 6E 74 74 62 6C 7B 5C 66 30
5C 66 6E 69 6C 20 4D 53 20 53 61 6E 73 20 53 65 72 69
66 3B 7D 7D 0D 0A 5C 76 69 65 77 6B 69 6E 64 34 5C 75
63 31 5C 70 61 72 64 5C 66 30 5C 66 73 33 32 20 31 39
39 38 32 37 32 30 0D 0A 5C 70 61 72 20 7D 0D 0A 00 20
12 10 6E 13 30 13 33 13 33 37 13 30 13 C6 F3 F0 ED E0
EB 20 5B 52 55 53 5D 11 12 10 6E 13 31 13 33 13 34 13
30 13 CD E0 E7 E2 E0 ED E8 E5 11 12 10 6E 13 32 13 34
13 31 13 31 13 D3 D7 C5 CD DB C5 20 C7 C0 CF C8 D1 CA
C8 20 CE D0 CB CE C2 D1 CA CE C3 CE 20 C3 CE D1 D3 C4
C0 D0 D1 D2 85
Или
{\rtf1\ansi\ansicpg1251\deff0\deflang1049{\fonttbl{\f0\fnil
MS
Sans
19982720..\par
Serif;}}..\viewkind4\uc1\pard\f0\fs32
}...
..n.0.3.37.0.Журнал
[RUS]...n.1.3.4.0.Название...n.2.4.1.1.УЧЕНЫЕЗАПИСКИОРЛОВСК
ОГОГОСУДАРСТ…
16
где «19982720» – опять же значение поля «ISSN/Код НЭБ», а «УЧЕНЫЕ
ЗАПИСКИ ОРЛОВСКОГО ГОСУДАРСТ…» - это значение поля «Название».
Задача создания файла данного формата из получаемого в процессе работы
файла .XML [7] является неотъемлемой частью прохождения пути от исходного
.PDF до готовности принятия в электронную библиотеку eLibrary
сборника
научных работ
ГЛАВА 2. ПРОГРАММНАЯ РЕАЛИЗАЦИЯ
2.1
Разработка модуля выделения элементов PDF-документа.
Реализация работы имеет три стадии: автоматическое предварительное
представление PDF-файла в табличную структуру, с которой можно работать
программно, создание упорядоченного XML-файла с нужной выделенной
информацией и в завершение обработка и запись данных в SAP-файл.
Для выделения и обработки необходимых для создания требуемого XMLфайла данных будут использоваться методы библиотеки SAX [3] языка Java [1].
Каждый раз при нахождении парсером открывающего тега ‘<’ вызывается
startElement() и обрабатывает информацию XML [7] в соответствии с кодом,
находящемся в данном методе.
public
startElement(String urname,
String
lName,
defname,
Attributes
atts)
SAXException {
Здесь urname - это пространство имен, lName — локальное имя элемента, defName
- это комбинация локального имени с пространством имен (разделяется
двоеточием) и atts — атрибуты данного элемента.
17
Далее следуют условия метода, специфичные для данной работы: если
рассмотренные ранее параметры токена соответствуют заранее известным
благодаря
анализу
исходных
файлов
параметрам,
то
устанавливается
положительное значение логической переменной, соответствующей данному
блоку.
if(defName.equalsIgnoreCase("TOKEN"))&&(attributes.e
qualsIgnoreCase("font-name="cambria"
"
font-
size="9"font-color="#221e1f"rotation="0"
angle="0"")){
= true;
}
}
public
String
defName,
startElement(String urname,
attributes)
throws
{
if(defName.equalsIgnoreCase("TOKEN"))&&(attributes.e
qualsIgnoreCase("font-name="CenturySchoolbook"
serif="yes"
"
italic="no"
font-size="32.5001"
"
rotation="0" ="0"")){
jrntitle = true;
}
}
void
lName,String defName,
startElement(String
attributes)
SAXException {
urname,
18
if(defName.equalsIgnoreCase("TOKEN"))&&(attributes.e
qualsIgnoreCase("fontname="TimesNewRomanPS"symbolic="yes"
"
italic="no"
font-size="31.2501" " rotation="0" angle="0"")){
= true;
}
}
void startElement(String urname,
String
lName,
,
Attributes
attributes)
SAXException {
" serif="yes" fixed-width="yes" " italic="no" fontsize="12" " rotation="0" angle="0"")){
= true;
}
}
void startElement(String urname,
lName,
String , Attributes attributes)
SAXException {
" bold="yes" italic="no" ="10" font-color="#221e1f"
rotation="0" ="0"")){
arttitle = true;
}
}
19
Далее используется метод characters, который требуется для самого процесса
выделения текста из найденных блоков (тех, чьи логические переменные
отмечены положительно). Если блок найден, то его бинарная текстовая
информация
без
соответствующая
разметки
сохраняется
логическая
в
переменная
отдельную
помечается
переменную
как
предотвращения еѐ повторного использования:
void characters(char [], int start, int length)
SAXException {
System.out.println(new , start, ));
if (segtitle) {
System.out.println("segtitle : "
+ new , start, length));
new , start, length)) =
segtitle_string;
= false; }
if (jrntitle) {
: "
+ new String(ch, start, ));
new String(ch, start, )) = String ;
jrntitle = false; }
if () {
ложь
и
для
20
System.out.println("jvolUni : "
+ new String(ch, , length));
new String(ch, , length)) =
jvolUni_string;
jvolUni = ; }
if (jdateUni) {
System.out.println("jdateUni : "
+ new , start, length));
new , start, )) = String jdateUni_string;
= false; }
if (arttitle) {
: "
+ new String(ch, start, ));
new String(ch, , length)) = String ;
arttitle = false;
}
}
Итак, когда все текстовые данные каждого из найденных блоков выделены в
отдельные переменные, можно начинать запись промежуточного файла формата
XML [7], требуемого для формирования итогового файла SAP.
2.2 Разработка модуля формирования файла XML.
21
Промежуточный файл имеет стандартную структуру XML [7]. Каждый из тегов
содержит в себе информацию из блоков, выделенных в предыдущих параграфах.
Рисунок 3 - фрагмент промежуточного XML-файла
Для
создания
данного
файла
в
работе
используются
средства
языка
программирования Java [1].
В начале данной стадии работы требуется определить потоки входящего и
выходящего файлов для работы первоначального конвертера и итоговой записи
соответственно (при запуске программы пользователь через пробел будет
указывать имя входящего и желаемое имя исходящего файлов):
File infile = new File(args[0]);
inputStream = new FileInputStream(infile);
22
File outfile = new File(args[1]); //= new [1]);
FileOutputStream fos = new );
Далее
необходимо
создать
строковую
переменную,
которая
является
необходимой для присутствия в файле для соответствия требуемым стандартам
XML [7] и начать формировать строки для записи на основе полученных во время
процесса выделения текстовых блоков из исходного файла:
String beg = “<?xml version=\"1.0\" \" ?>”;
String
=
“<segtitle
lang=\"RUS\">”
+
“”
+
“</segtitle>”;
+ Jrntitle_string + ;
+
+ ;
+ jdateUni_string + ;
+ arttitle_string + ;
Далее следует представить подготовленные строки в виде бинарных данных и
начать конечную стадию работы данного шага – создание файла XML [7], очистка
и закрытие потока записи, завершение работы модуля.
byte [] = beginning.getBytes("UTF-8");
byte_ = .getBytes("UTF-8");
_byte = .getBytes("UTF-16");
23
);
fos.write(byte_);
fos.write(_byte);
fos.flush();
fos.close();
}
(Exception e) {
e.printStackTrace();
}
}
}
2.3 Приемы лексического анализа текста XML-файла.
По итогам разбора XML-файла понятно, что в работе требуется реализовать
алгоритм отсева текста на русском языке от текста на английском для дальнейшей
структурированной записи в SAP-файл - иначе он не будет соответствовать
стандартам библиотеки eLibrary.
24
На выбранном мной языке программирования это можно реализовать с
помощью подключения крупных библиотек анализа текста, например Google
Language Detection Library for Java [5]. Но на практике их использование влечет за
собой массу проблем – отсутствуют преимущества в виде кроссплатформенности
и простоте развертывания и настройки, неочевидные и неожиданные ошибки в
работе, связанные с обширностью и широкой направленностью библиотек, в разы
увеличиваются затраты ресурсов персонального компьютера при выполнении
работы, появляется требование в виде постоянного доступа в сети Интернет для
доступа к API, уменьшается безопасность работы с данными из-за отправки
текстовой информации научных работ на сервер сторонней организации. В связи
со всем вышеперечисленным был реализован алгоритм определения языка строки.
Далее приведѐн фрагмент кода алгоритма:
public static boolean main(String[] args) throws
Exception {
//Создаѐм
входной
поток,
из
которого
читаться
будет
текст:
InputStream
inputStream
=
new
InputStream(intext);
//Создаѐм шаблон из регулярного выражения, по
которому
будет
проверяться
отсутствие
Pattern
текст
на
наличие
русскоязычных
pattern
=
или
символов:
Pattern.compile(
"[" +
//начало списка
допустимых
символов
"а-яА-ЯѐЁ"
+
//буквы
русского
алфавита
"]" +
//конец списка
допустимых
символов
"*");
//допускается наличие
25
указанных символов в любом количестве
//Далее
проверяем
критериям поиска
true
или
false
символов,
false
Matcher
if
наличие
совпадений
по
и возвращаем логическое значение
(true
-
-
наличие
соответственно
matcher
=
matcher.matches
русскоязычных
отсутствие):
pattern.matcher(intext);
!=
""
return
true;
}
2.4 Разработка модуля формирования файла SAP.
В электронную библиотеку eLibrary, принимающую сборники научных
статей,
рассматривающихся
в
данной
работе,
издания
поступают
в
специализированном формате .SAP.
SAP-файл представляет собой упорядоченную последовательность байт,
имеющую определенную структуру, описанную в главе 1.
Задача создания файла данного формата из получаемого в процессе работы
файла XML [7] является неотъемлемой частью прохождения пути от исходного
26
PDF до готовности принятия в электронную библиотеку eLibrary
сборника
научных работ.
В процессе реализации программы возникла задача выбора алгоритма
парсинга XML-файла. Мной было принято решение использовать SAX [3].
SAX («Simple API for XML») [3] – способ последовательного чтения/записи XMLфайлов. Одно из ключевых преимуществ SAX [3] заключается в том, что для его
работы требуется намного меньше памяти для обработки документа XML, чем
при использовании других алгоритмов. При работе SAX [3] требуемый объем
памяти не возрастает вместе с увеличением размера обрабатываемого файла.
Например, при обработке документа объемом в сто килобайт с помощью
синтаксического анализатора DOM («Document Object Model») [8] необходимо
около одного мегабайта памяти, при использовании для обработки этого же
документа с помощью синтаксического анализатора SAX [3] памяти необходимо
намного меньше. Если программа будет работать с большими документами,
использование синтаксического анализатора SAX [3] наиболее разумно, особенно
если не нужно изменять содержание документа, как в данной задаче.
Далее будут рассмотрены и пояснены фрагменты программы, решающей
задачу создания итогового файла .SAP из .XML-файла, получаемого в данной
работе.
Подключаем все необходимые для работы модули, создаѐм класс под названием
parser:
import java.io.*;
import javax.xml.*;
import org.xml.sax.*;
public
parser {
27
public
void
args([]) {
Для получения SAX-анализатора используется приведенная ниже команда:
SAXParserFactory
factory
=
SAXParserFactory.newInstance();
SAXParser saxParser = factory.newSAXParser();
В
программе
определяем
обработчик
событий
DefaultHandler,
создаем
переменные типа boolean, которые далее будут сигнализировать о нахождении
того или иного элемента в XML-файле:
DefaultHandler handler = new DefaultHandler() {
boolean oper = false;
boolean date = false;
boolean cntart = false;
boolean cntnode = false;
boolean cs = false;
boolean journalInfo_lang = false;
boolean jrntitle = false;
boolean jrntitlevar = false;
28
boolean publ = false;
boolean placepubl = false;
boolean issn = false;
boolean jrncode = false;
boolean jnumUni = false;
boolean istitle = false;
boolean jdateUni = false;
boolean pages = false;
boolean loc = false;
boolean segtitle = false;
boolean fpageart = false;
boolean lpageart = false;
boolean author_num = false;
boolean correspondent = false;
boolean surname = false;
boolean fname = false;
boolean auemail = false;
boolean auwork = false;
boolean auinf = false;
Для использования SAX-анализатора необходимо создать обработчик событий,
которые происходят во
время
разбора XML-документа.
В интерфейсе
29
DefaultHandler определено несколько методов обратного вызова, к которым
обращается анализатор:
-Методы startElement() и endElement() вызываются при получении открывающего
и закрывающего дескрипторов.
-Метод characters() вызывается при получении символьных данных.
-Методы startDocument() и endDocument() вызываются в начале и конце
документа.
Используем методы startElement() и endElement() так, чтобы программа была
более наглядной — при получении открывающего и закрывающего дескрипторов
будут напечатаны стартовый и конечный элемент в терминале:
public
void
startElement(String
urname,
String
lName,
String
defName,
Attributes
attributes)
throws SAXException {
System.out.println("Start
Element
defName);
if
(defName.equalsIgnoreCase("OPERATOR")) {
oper = true;
}
:"
+
30
if
(defName.equalsIgnoreCase("DATE")) {
date = true;
}
if
(defName.equalsIgnoreCase("cntArticle")) {
cntart = true;
}
if
(defName.equalsIgnoreCase("cntnode")) {
cntnode = true;
}
if
(defName.equalsIgnoreCase("cs")) {
cs = true;
}
if
(defName.equalsIgnoreCase("jrntitle")) {
jrntitle = true;
31
}
if
(defName.equalsIgnoreCase("jrntitlevar")) {
jrntitlevar = true;
}
if
(defName.equalsIgnoreCase("publ")) {
publ = true;
}
if
(defName.equalsIgnoreCase("placepubl")) {
placepubl = true;
}
if
(defName.equalsIgnoreCase("issn")) {
issn = true;
}
if
(defName.equalsIgnoreCase("jrncode")) {
32
jrncode = true;
}
if
(defName.equalsIgnoreCase("jnumUni")) {
jnumUni = true;
}
if
(defName.equalsIgnoreCase("istitle")) {
istitle = true;
}
if
(defName.equalsIgnoreCase("jdateUni")) {
jdateUni = true;
}
if
(defName.equalsIgnoreCase("pages")) {
pages = true;
}
33
if
(defName.equalsIgnoreCase("loc")) {
loc = true;
}
if
(defName.equalsIgnoreCase("segtitle")) {
segtitle = true;
}
if
(defName.equalsIgnoreCase("fpageart")) {
fpageart = true;
}
if
(defName.equalsIgnoreCase("lpageart")) {
lpageart = true;
}
}
34
public void endElement(String urname,
String lName,
String
defName)
throws
System.out.println("End
Element
SAXException {
:" + defName);
Далее используем метод characters для получения данных каждого требуемого
поля. Для наглядности каждое найденное значение печатается в терминале:
public
void
characters(char
ch[],
int
start,
int
length)
throws SAXException {
System.out.println(new
String(ch,
start,
length));
if (oper) {
System.out.println("Operator
: "
+
new
String(ch,
length));
oper = false;
}
start,
35
if (date) {
System.out.println("Date : "
+
new
String(ch,
start,
length));
date = false; }
if (cntart) {
System.out.println("cntart
:
"
+
new
String(ch,
start,
length));
cntart = false; }
if (cntnode) {
System.out.println("Node : "
+
new
String(ch,
start,
length));
cntnode = false; }
if (cs) {
System.out.println("Cs : "
+
length));
new
String(ch,
start,
36
cs = false; }
if (jrntitle) {
System.out.println("jrntitle
: "
+
new
String(ch,
start,
length));
jrntitle = false; }
if (jrntitlevar) {
System.out.println("jrntitlev
ar : "
+
new
String(ch,
start,
length));
jrntitlevar = false; }
if (publ) {
System.out.println("publ : "
+
new
String(ch,
start,
length));
publ = false; }
if (placepubl) {
System.out.println("placepubl
37
: "
+
new
String(ch,
start,
length));
placepubl = false; }
if (issn) {
String
issn_string
=
new
String(ch, start, length); ///!!!
System.out.println("ISSN : "
+
new
String(ch,
start,
length));
issn = false; }
if (jrncode) {
System.out.println("jrncode :
"
+
new
String(ch,
start,
length));
jrncode = false;
if (jnumUni) {
System.out.println("jnumUni :
38
"
+
new
String(ch,
start,
length));
jnumUni = false; }
if (istitle) {
System.out.println("istitle :
"
+
new
String(ch,
start,
length));
istitle = false; }
if (jdateUni) {
System.out.println("jdateUni
: "
+
new
String(ch,
start,
length));
jdateUni = false; }
if (pages) {
System.out.println("pages : "
+
new
String(ch,
length));
pages = false; }
start,
39
if (loc) {
System.out.println("loc : "
+
new
String(ch,
start,
length));
loc = false; }
if (segtitle) {
System.out.println("segtitle
: "
+
new
String(ch,
start,
length));
segtitle = false; }
if (fpageart) {
System.out.println("fpageart
: "
+
new
String(ch,
length));
fpageart = false; }
start,
40
Создав файловый поток FileInputStream и объявив его входным источником для
объекта XML можно запускать парсер с помощью команды saxParser.parse (перед
этим можно установить кодировку входного источника, в нашем случае
необходима UTF-16LE):
File infile = new File(args[0]);
InputStream
inputStream
=
new
FileInputStream(infile);
InputSource
is
=
new
InputSource(inputStream);
is.setEncoding("UTF-16LE");
saxParser.parse(is, handler);
Финальный шаг работы программы — запись полученных данных в файл .SAP в
соответствии с его структурой, описанной ранее. Создав выходной файловый
поток FileOutputStream и требуемые байтовые массивы, которые либо неизменны
в структуре файла SAP, либо получены в результате парсинга XML-файла, можно
начинать финальную процедуру записи выходного бинарного файла:
File outfile = new File(args[1]); //"newfile.sap"
FileOutputStream
fos
=
new
FileOutputStream(outfile);
String
beginning
=
"{sap1}#j#RUS#91###n#0#3#4#0#ISSN/КодНЭБ###n#1#4#1#1
#";
41
String
rtf1
="#{\\rtf1\\ansi\\ansicpg1251\\deff0\\deflang1049{\\
fonttbl{\\f0\\fnil
MS
Sans
Serif;}}"
+
"\n"
+
"\\viewkind4\\uc1\\pard\\f0\\fs32 ";
byte
b[]
=
beginning.getBytes("windows-
1251");
byte
b_issn[]
=
issn_string.getBytes("windows-1251");
byte
b_rtf1[]
=
1251");
fos.write(b);
fos.write(b_rtf1);
fos.write(b_issn);
fos.write(b_rtf2);
fos.flush();
fos.close();
rtf1.getBytes("windows-
42
ГЛАВА 3. ПРАКТИЧЕСКОЕ ИСПОЛЬЗОВАНИЕ
Готовая
скомпилированная
программа
является
консольной
утилитой,
вызываемая следующей командой:
pdf2sap <путь до исходного файла и его имя>
Рисунок 3 – процесс запуска программы
Во время выполнения программа не занимает ресурсы персонального компьютера
до состояния невозможности многозадачного использования, что несомненно
важно в реалиях работы персонала электронных библиотек. В процессе работы в
каталоге нахождения оригинального файла ожидается появление подкаталога с
временными файлами и промежуточного XML-файла.
Рисунок 4 – временные файлы в каталоге с оригинальным файлом PDF
43
Время выполнения алгоритма зависит от факторов объема входных файлов и
конфигурации рабочей станции, обычно не занимая длительное время. По
окончании работы программы в директории исходного PDF-файла будет
находиться файл с расширением .SAP, имеющий то же имя.
Рисунок 5 – состав каталога с оригинальным PDF-файлом после завершения
работы программы
Полученный SAP-файл имеет правильную структуру, соответствующую
требуемой программой SarticleXML, используемой при работе со сборниками
научных работ.
Рисунок 6 – окно программы SarticleXML с открытым SAP-файлом
44
45
ЗАКЛЮЧЕНИЕ
В результате выполнения выпускной квалификационной работы магистра были
достигнуты поставленные цели и решены сформулированные задачи. Выбрана и
обоснована технология извлечения текста из файла формата PDF, определены
устойчивые критерии идентификации структурных элементов
документа,
разработано ПО для выделения текста структурных элементов и получения
файлов разметки в формате *.SAP электронной библиотеки eLibrary.
Получившийся продукт является кроссплатформенным, прост в настройке
и в полной мере соответствует стандартам составления сборников научных
статей. С точки зрения конечного пользователя программа проста в работе и не
требует никаких дополнительных знаний и навыков.
46
СПИСОК ЛИТЕРАТУРЫ
1. Java Platform Standard Edition 8 Documentation [Электронный ресурс]. - Режим
доступа: https://docs.oracle.com/javase/8/docs/. - Дата доступа: 25.06.2018.
2. pdf2xml
[Электронный
ресурс].
Режим
-
доступа:
https://github.com/eliask/pdf2xml. - Дата доступа: 25.06.2018.
3. Simple
API
for
XML
[Электронный
ресурс].
-
Режим
доступа:
-
Режим
доступа:
http://www.saxproject.org/. - Дата доступа: 25.06.2018.
4. iText
7
Community
API
[Электронный
ресурс].
http://itextsupport.com/apidocs/itext7/latest/. - Дата доступа: 25.06.2018.
5. Google Language Detection Library for Java [Электронный ресурс]. - Режим
доступа: https://code.google.com/archive/p/language-detection/. - Дата доступа:
25.06.2018.
6. Xpdf
Open
Source
[Электронный
ресурс].
-
Режим
доступа:
https://www.xpdfreader.com/opensource.html. - Дата доступа: 25.06.2018.
7. Extensible Markup Language (XML) 1.0 (Fifth Edition) [Электронный ресурс]. Режим доступа: https://www.w3.org/TR/xml/. - Дата доступа: 25.06.2018.
8. W3C
DOM4
[Электронный
ресурс].
-
https://www.w3.org/TR/dom/. - Дата доступа: 25.06.2018.
Режим
доступа:
47
Приложение
Приложение 1.
Модуль итоговой записи SAP-файла.
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
public class semant {
public static void main(String args[]) {
SAXParserFactory
factory
=
SAXParserFactory.newInstance();
SAXParser
saxParser
=
factory.newSAXParser();
DefaultHandler
DefaultHandler() {
handler
=
new
48
boolean cntArticle = false;
boolean jrntitle = false;
boolean publ = false;
boolean issn = false;
boolean jrncode = false;
boolean jrntitle = false;
boolean jrntitlevar = false;
boolean jvolUni = false;
boolean placepubl = false;
boolean istitle = false;
boolean jdateUni = false;
boolean pages = false;
boolean loc = false;
boolean segtitle = false;
boolean fpageart = false;
boolean lpageart = false;
boolean author_num = false;
boolean correspondent = false;
boolean surname = false;
boolean fname = false;
boolean auemail = false;
boolean auwork = false;
boolean auinf = false;
public void startElement(String
uri, String localName,
String qName, Attributes
attributes)
49
throws SAXException {
if
(qName.equalsIgnoreCase("TOKEN"))
&&
(attributes.equalsIgnoreCase("fontname="cambria"
size="9"
bold="yes"
italic="no"
font-color="#221e1f"
font-
rotation="0"
angle="0"")){
segtitle = true;
}
}
public void startElement(String
uri, String localName,
String qName, Attributes
attributes)
throws SAXException {
if
(qName.equalsIgnoreCase("TOKEN"))
&&
(attributes.equalsIgnoreCase("fontname="CenturySchoolbook" serif="yes" bold="yes"
italic="no"
font-size="32.5001"
color="#221e1f" rotation="0" angle="0"")){
jrntitle = true;
}
font-
50
}
public void startElement(String
uri, String localName,
String qName, Attributes
attributes)
throws SAXException {
if
(qName.equalsIgnoreCase("TOKEN"))
&&
(attributes.equalsIgnoreCase("fontname="TimesNewRomanPS" symbolic="yes" bold="yes"
italic="no"
font-size="31.2501"
font-
color="#221e1f" rotation="0" angle="0"")){
jvolUni = true;
}
}
public void startElement(String uri, String
localName,
String qName, Attributes
attributes)
throws SAXException {
if
(qName.equalsIgnoreCase("TOKEN"))
&&
(attributes.equalsIgnoreCase("fontname="timesnewromanpsmt"
serif="yes"
fixed-width="yes"
symbolic="yes"
bold="no"
51
italic="no" font-size="12" font-color="#221e1f"
rotation="0" angle="0"")){
jdateUni = true;
}
}
public void startElement(String uri, String
localName,
String qName, Attributes
attributes)
throws SAXException {
if
(qName.equalsIgnoreCase("TOKEN"))
&&
(attributes.equalsIgnoreCase("fontname="cambria"
size="10"
bold="yes"
italic="no"
font-color="#221e1f"
font-
rotation="0"
angle="0"")){
arttitle = true;
}
}
public
void
characters(char
ch[], int start, int length)
throws SAXException {
System.out.println(new
String(ch, start, length));
52
if (segtitle) {
System.out.println("segtitle : "
+ new String(ch,
start, length));
new
String(ch,
start,
length)) = String segtitle_string;
segtitle = false;
}
if (jrntitle) {
System.out.println("jrntitle : "
+ new String(ch,
start, length));
new
String(ch,
start,
length)) = String jrntitle_string;
jrntitle = false;
}
if (jvolUni) {
System.out.println("jvolUni : "
+ new String(ch,
start, length));
53
new
String(ch,
start,
length)) = String jvolUni_string;
jvolUni = false;
}
if (jdateUni) {
System.out.println("jdateUni : "
+ new String(ch,
start, length));
new
String(ch,
start,
length)) = String jdateUni_string;
jdateUni = false;
}
if (arttitle) {
System.out.println("arttitle : "
+ new String(ch,
start, length));
new
String(ch,
length)) = String arttitle_string;
arttitle = false;
start,
54
}
}
File infile = new File(args[0]);
InputStream
inputStream
=
new
FileInputStream(infile);
InputSource
is
=
new
InputSource(inputStream);
is.setEncoding("UTF-8");
saxParser.parse(is, handler);
File outfile = new File(args[1]);
FileOutputStream
fos
=
new
[]
=
FileOutputStream(outfile);
byte
b_segtitle
segtitle_string.getBytes("windows-1251");
byte
b_jrntitle
[]
=
jrntitle_string.getBytes("windows-1251");
byte
b_jvolUni
[]
=
jvolUni_string.getBytes("windows-1251");
byte
b_jrntitle
[]
=
jrntitle_string.getBytes("windows-1251");
byte
b_jdateUni
[]
jdateUni_string.getBytes("windows-1251");
fos.write(b_beginning);
=
55
fos.write(b_segtitle);
fos.flush();
fos.close();
Приложение 2.
56
Модуль вызова и первичного использования утилиты pdf2xml
#include
<aconf.h>
#include
<stdio.h>
#include
<stdlib.h>
#include
<stddef.h>
#include
<string.h>
#include
"parseargs.h"
#include
"GString.h"
#include
"gmem.h"
#include
"GlobalParams.h"
#include
"Object.h"
#include
"Stream.h"
#include
"Array.h"
#include
"Dict.h"
#include
"XRef.h"
#include
"Catalog.h"
#include
"Page.h"
#include
"PDFDoc.h"
#include
"XmlOutputDev.h"
#include
"CharTypes.h"
#include
"UnicodeMap.h"
#include
"Error.h"
#include
"config.h"
#include
"Parameters.h"
#include
"Outline.h"
#include
"PDFDocXrce.h"
57
#include
<sys/types.h>
#include
<dirent.h>
#include
<iostream>
using
namespace
#include
std;
"ConstantsUtils.h"
using
namespace
ConstantsUtils;
#include
"ConstantsXML.h"
using
namespace
ConstantsXML;
void
removeAlreadyExistingData(GString
static
const
char
cvsid[]
=
*dir);
"$Revision$";
static
int
firstPage
=
1;
static
int
lastPage
=
0;
static
GBool
physLayout
static
GBool
verbose
static
static
char
char
=
gTrue;
=
cfgFileName[256]
gFalse;
=
XMLcfgFileName[256]
=
"";
"";
static
GBool
noText
=
gFalse;
static
GBool
noImage
=
gFalse;
static
GBool
outline
=
gFalse;
static
GBool
cutPages
=
gFalse;
58
static
GBool
blocks
=
gFalse;
static
GBool
fullFontName
=
gFalse;
static
GBool
noImageInline
=
gFalse;
static
GBool
annots
=
gFalse;
static
char
ownerPassword[33]
=
"\001";
static
char
userPassword[33]
=
"\001";
static
GBool
static
quiet
GBool
static
printVersion
GBool
static
{"-f",
"first
argFlag,
"do
&verbose,
{"-noImage",
0,
attributes"},
argFlag,
not
0,
convert"},
pdf
{"-noText",
0,
convert"},
to
"display
{
&lastPage,
page
{"-verbose",
"\001";
=
to
argInt,
"last
=
&firstPage,
page
{"-l",
gFalse;
argDesc[]
argInt,
gFalse;
=
namespaceUri[256]
ArgDesc
gFalse;
=
printHelp
char
static
=
&noText,
extract
textual
argFlag,
0,
objects"},
&noImage,
0,
"do not extract Images (Bitmap and Vectorial)"},
{"-noImageInline", argFlag,
"do
not
include
{"-outline",
"create
inline
argFlag,
an
{"-annotation",
"create
images
an
&noImageInline,
in
the
stream"},
&outline,
outline
argFlag,
annotations
file
&annots,
file
0,
0,
xml"},
0,
xml"},
59
{"-cutPages",
"cut
argFlag,
all
pages
{"-blocks",
&cutPages,
in
separately
argFlag,
0,
files"},
&blocks,
0,
"add blocks informations whithin the structure"},
{"-fullFontName", argFlag,
"fonts
names
{"-nsURI",
&fullFontName,
are
not
0,
normalized"},
argString,
namespaceUri,
sizeof(namespaceUri),
"add
the
specified
{"-opw",
namespace
argString,
URI"},
ownerPassword,
sizeof(ownerPassword),
"owner
password
(for
{"-upw",
encrypted
argString,
files)"},
userPassword,
sizeof(userPassword),
"user
password
{"-q",
"don't
argFlag,
print
{"-v",
"print
(for
any
{"-h",
"print
{"-help",
"print
{"--help",
"print
{"-?",
"print
{"--saveconf",
XMLcfgFileName,
argFlag,
usage
argFlag,
usage
argFlag,
usage
argFlag,
usage
files)"},
&quiet,
messages
argFlag,
copyright
encrypted
0,
or
errors"},
&printVersion,
and
version
0,
info"},
&printHelp,
0,
information"},
&printHelp,
0,
information"},
&printHelp,
0,
information"},
&printHelp,
0,
information"},
argString,
sizeof(XMLcfgFileName),
60
"save all command line parameters in the specified
XML
//
<file>"},
{"-conf",
argString,
cfgFileName,
sizeof(cfgFileName),{NULL}};
int
main(int
argc,
char
*argv[])
PDFDocXrce
{
*doc;
GString
*fileName;
GString
*textFileName;
GString
*dataDirName;
GString
*shortFileName;
GString
*annotationfile;
GString
*ownerPW,
*userPW;
GString
*nsURI;
GString
*cmd;
XmlOutputDev
*xmlOut;
GBool
ok;
char
*p;
int
exitCode;
char
*temp;
exitCode
ok
=
=
parseArgs(argDesc,
if
99;
&argc,
argv);
(XMLcfgFileName[0]){}
else{
if (!ok || argc < 2 || argc > 3 || printVersion
||
printHelp)
{
61
fprintf(stderr,
PDFTOXML_NAME);
fprintf(stderr,
"
version
");
fprintf(stderr,
PDFTOXML_VERSION);
fprintf(stderr,
"\n");
fprintf(stderr, "(Based on Xpdf version %s,
%s)\n",
xpdfVersion,
fprintf(stderr,
xpdfCopyright);
"%s\n",
"Copyright
2004-2006
XRCE");
if
(!printVersion)
printUsage("pdftoxml",
{
"<PDF-file>
file>]",
[<xml-
argDesc);
}
goto
err0;
}
}
cmd
globalParams
parameters
=
new
=
new
=
GString();
GlobalParams(cfgFileName);
new
Parameters();
if(noImage){
parameters->setDisplayImage(gFalse);
cmd->append("-noImage
}
else{
parameters->setDisplayImage(gTrue);
}
if(noText){
");
62
parameters->setDisplayText(gFalse);
cmd->append("-noText
");
}
else{
parameters->setDisplayText(gTrue);
}
if(outline){
parameters->setDisplayOutline(gFalse);
cmd->append("-outline
");
}
else{
parameters->setDisplayOutline(gTrue);
}
if(cutPages){
parameters->setCutAllPages(gFalse);
cmd->append("-cutPages
");
}
else{
parameters->setCutAllPages(gTrue);
}
if(blocks){
parameters->setDisplayBlocks(gTrue);
cmd->append("-blocks
}
else{
parameters->setDisplayBlocks(gFalse);
");
63
}
if(fullFontName){
parameters->setFullFontName(gTrue);
cmd->append("-fullFontName
");
}
else{
parameters->setFullFontName(gFalse);
}
if(noImageInline){
parameters->setImageInline(gTrue);
cmd->append("-noImageInline
");
}
else{
parameters->setImageInline(gFalse);
}
if
(quiet)
{
globalParams->setErrQuiet(quiet);
}
if
(verbose){
cmd->append("-verbose
");
}
if
(ownerPassword[0]
ownerPW
}
=
new
!=
'\001')
{
GString(ownerPassword);
else
{
64
ownerPW
=
NULL;
}
if
(userPassword[0]
userPW
=
!=
new
}
userPW
'\001')
{
GString(userPassword);
else
{
=
NULL;
}
if
(namespaceUri[0]
nsURI
=
!=
new
cmd->append("-nsURI
'\001')
{
GString(namespaceUri);
")->append(nsURI)->append("
");
}
nsURI
else
{
=
NULL;
}
if
(XMLcfgFileName
&&
XMLcfgFileName[0]){
parameters>saveToXML(XMLcfgFileName,firstPage,lastPage);
}
if
(argc
fileName
doc
=
new
if
<
=
2)
new
PDFDocXrce(fileName,
(userPW)
delete
{goto
err0;}
GString(argv[1]);
ownerPW,
userPW);
{
userPW;
}
if
(ownerPW)
{
65
delete
ownerPW;
}
if
(!doc->isOk())
exitCode
{
=
1;
goto
err2;
}
if
(!doc->okToCopy())
fprintf(stderr,
"\n\nYou
are
not
supposed
to
copy this document...\n\n");
if
(argc
textFileName
==
=
3)
new
{
GString(argv[2]);
temp = textFileName->getCString() + textFileName>getLength()
-
4;
if (!strcmp(temp, EXTENSION_XML) || !strcmp(temp,
EXTENSION_XML_MAJ))
{
shortFileName
>getCString(),
=
new
GString(textFileName-
textFileName->getLength()
-
}else
4);
{
shortFileName
=
new
GString(textFileName);
}
}
else
{
p = fileName->getCString() + fileName->getLength()
-
4;
if
(!strcmp(p,
EXTENSION_PDF)
||
!strcmp(p,
EXTENSION_PDF_MAJ))
{
textFileName
>getCString(),
=
new
GString(fileName-
fileName->getLength()
-
4);
66
shortFileName
=
}
new
GString(textFileName);
else
textFileName
{
=
shortFileName
=
fileName->copy();
new
GString(textFileName);
}
textFileName->append(EXTENSION_XML);
}
if
(annots){
annotationfile
=
new
GString(shortFileName);
annotationfile->append("_");
annotationfile->append(NAME_ANNOT);
annotationfile->append(EXTENSION_XML);
cmd->append("-annotation
");
}
if
(firstPage
firstPage
<
1)
{
=
1;
}
if
(firstPage!=1){
char*
temp=(char*)malloc(10*sizeof(char));
sprintf(temp,"%d",firstPage);
cmd->append("-f
")->append(temp)->append("
");
free(temp);
}
if
(lastPage!=0){
int
last
=
lastPage;
67
if
(lastPage
last
>
doc->getNumPages()){
=
doc->getNumPages();
}
char*
temp=(char*)malloc(10*sizeof(char));
sprintf(temp,"%d",last);
cmd->append("-l
")->append(temp)->append("
");
free(temp);
}
if (lastPage < 1 || lastPage > doc->getNumPages()) {
lastPage
=
doc->getNumPages();
}
xmlOut
=
new
XmlOutputDev(textFileName,
fileName,
doc->getCatalog(), physLayout, verbose, nsURI, cmd);
if
(xmlOut->isOk())
dataDirName
=
new
{
GString(textFileName);
dataDirName->append(NAME_DATA_DIR);
removeAlreadyExistingData(dataDirName);
if (annots){
xmlDocPtr
docAnnotXml;
xmlNodePtr
docroot;
docAnnotXml
=
xmlNewDoc((const
xmlChar*)VERSION);
docAnnotXml->encoding
=
xmlStrdup((const
xmlChar*)ENCODING_UTF8);
docroot
=
xmlChar*)TAG_ANNOTATIONS);
xmlNewNode(NULL,(const
68
xmlDocSetRootElement(docAnnotXml,docroot);
doc->displayPages(xmlOut,
lastPage,
72,
72,
0,
docroot,
gTrue,
gTrue,
firstPage,
gFalse);
xmlSaveFile(annotationfile>getCString(),docAnnotXml);
xmlFreeDoc(docAnnotXml);
}
else{
doc->displayPages(xmlOut,
lastPage,
72,
72,
0,
NULL,
gTrue,
gTrue,
firstPage,
gFalse);
}
if
(outline){
if
(doc->getOutline()){
xmlOut->initOutline(doc->getNumPages());
xmlOut->generateOutline(doc-
>getOutline()->getItems(), doc, 0);
xmlOut->closeOutline(shortFileName);
}
}
}
else
{
delete
exitCode
goto
}
xmlOut;
=
2;
err3;
69
delete
xmlOut;
exitCode
=
if
0;
(nsURI)
{
delete
nsURI;
}
err3:
delete
textFileName;
err2:
delete
doc;
delete
globalParams;
delete
parameters;
delete
cmd;
err0:
Object::memCheck(stderr);
gMemReport(stderr);
return
exitCode;
}
void
removeAlreadyExistingData(GString
*dir)
GString
{
*file;
struct
dirent
*lecture;
DIR
*rep;
rep
=
if
(rep
while
file
opendir(dir->getCString());
!=
((lecture
=
NULL)
{
=
readdir(rep))){
new
GString(dir);
70
file->append("/");
file->append(lecture->d_name);
std::remove(file->getCString());
}
if
(file)
closedir(rep);
}
}
delete
file;
1/--страниц
Пожаловаться на содержимое документа