I am a huge fan of Ben Marwick. He has so many useful pieces of code for the programming archaeologist or historian!

Edit July 17 1.20 pm: Mea culpa: I originally titled this post, ‘Doing OCR within R’. But, what I’m describing below – that’s not OCR. That’s extracting text from pdfs. It’s very fast and efficient, but it’s not OCR. So, brain fart. But I leave the remainder of the post as it was. For command line OCR (really, actual OCR) on a Mac, see the link to Ben Schmidt’s piece at the bottom. Sorry.

Edit July 17 10 pm: I am now an even bigger fan of Ben’s. He’s updated his script to either a) perform OCR by calling Tesseract from within R or b) grab the text layer from a pdf image. So this post no longer misleads. Thank you Ben!

Object Character Recognition, or OCR, is something that most historians will need to use at some point when working with digital documents. That is, you will often encounter pdf files of texts that you wish to work with in more detail (digitized newspapers, for instance). Often, there is a layer within the pdf image containing the text already: if you can highlight text by clicking and dragging over the image, you can copy and paste the text from the image. But this is often not the case, or worse, you have tens or hundreds or even thousands of documents to examine. There is commercial software that can do this for you, but it can be quite expensive

One way of doing OCR on your own machine with free tools, is to use Ben Marwick’s pdf-2-text-or-csv.r script for the R programming language. Marwick’s script uses R as wrapper for the Xpdf programme from Foolabs. Xpdf is a pdf viewer, much like Adobe Acrobat. Using Xpdf on its own can be quite tricky, so Marwick’s script will feed your pdf files to Xpdf, and have Xpdf perform the text extraction. For OCR, the script acts as a wrapper for Tesseract, which is not an easy piece of software to work with. There’s a final part to Marwick’s script that will pre-process the resulting text files for various kinds of text analysis, but you can ignore that part for now.

  1. Make sure you have R downloaded and installed on your machine (available from http://www.r-project.org/)
  2. Make sure you have Xpdf downloaded and installed (available from ftp://ftp.foolabs.com/pub/xpdf/xpdfbin-win-3.04.zip ). Make a note of where you unzipped it. In particular, you are looking for the location of the file ‘pdftotext.exe’. Also, make sure you know where ‘pdftoppm’ is located too (it’s in that download).
  3. Download and install Tesseract https://code.google.com/p/tesseract-ocr/ 
  4. Download and install Imagemagick http://www.imagemagick.org/
  5. Have a folder with the pdfs you wish to extract text from.
  6. Open R, and paste Marwick’s script into the script editor window.
  7. Make sure you adjust the path for “dest” and the path to “pdftotext.exe” to the correct location
  8. Run the script! But read the script carefully and make sure you run the bits you need. Ben has commented out the code very well, so it should be fairly straightforward.

Obviously, the above is framed for Windows users. For Mac users, the steps are all the same, except that you use the version of Xpdf, Tesseract, and Imagemagick built for IOS, and your paths to the other software are going to be different. And of course you’re using R for Mac, which means the ‘shell’ commands have to be swapped to ‘system’! (As of July 2014, the Xpdf file for Mac that you want is at ftp://ftp.foolabs.com/pub/xpdf/xpdfbin-mac-3.04.tar.gz ) I’m not 100% certain of any other Mac/PC differences in the R script – these should only exist at those points where R is calling on other resources (rather than on R packages). Caveat lector, eh?

The full R script may be found athttps://gist.github.com/benmarwick/11333467. So here is the section that does the text extraction from pdf images (ie, you can copy and highlight text in the pdf):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
###Note: there's some preprocessing that I (sg) haven't shown here: go see the original gist
 
################# Wait! ####################################
# Before proceeding, make sure you have a copy of pdf2text
# on your computer! Details: https://en.wikipedia.org/wiki/Pdftotext
 
# Tell R what folder contains your 1000s of PDFs
dest <- "G:/somehere/with/many/PDFs"
 
# make a vector of PDF file names
myfiles <- list.files(path = dest, pattern = "pdf",  full.names = TRUE)
 
# now there are a few options...
 
############### PDF to TXT #################################
# convert each PDF file that is named in the vector into a text file
# text file is created in the same directory as the PDFs
# note that my pdftotext.exe is in a different location to yours
lapply(myfiles, function(i) system(paste('"C:/Program Files/xpdf/bin64/pdftotext.exe"', paste0('"', i, '"')), wait = FALSE) )
 
# where are the txt files you just made?
dest # in this folder

And here’s the bit that does the OCR

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
</pre>
                     ##### Wait! #####
# Before proceeding, make sure you have a copy of Tesseract
# on your computer! Details & download:
# and a copy of ImageMagick: http://www.imagemagick.org/
# and a copy of pdftoppm on your computer!
# And then after installing those three, restart to
# ensure R can find them on your path.
# And note that this process can be quite slow...
 
# PDF filenames can't have spaces in them for these operations
# so let's get rid of the spaces in the filenames
 
sapply(myfiles, FUN = function(i){
  file.rename(from = i, to =  paste0(dirname(i), "/", gsub(" ", "", basename(i))))
})
 
# get the PDF file names without spaces
myfiles <- list.files(path = dest, pattern = "pdf",  full.names = TRUE)
 
# Now we can do the OCR to the renamed PDF files. Don't worry
# if you get messages like 'Config Error: No display
# font for...' it's nothing to worry about
 
lapply(myfiles, function(i){
  # convert pdf to ppm (an image format), using
  shell(shQuote(paste0("pdftoppm ", i, " -f 1 -l 10 -r 600 ocrbook")))
  # convert ppm to tif ready for tesseract
  shell(shQuote(paste0("convert *.ppm ", i, ".tif")))
  # convert tif to text file
  shell(shQuote(paste0("tesseract ", i, ".tif ", i, " -l eng")))
  # delete tif file
  file.remove(paste0(i, ".tif" ))
  })
 
# where are the txt files you just made?
dest # in this folder

Besides showing how to do your own OCR, Marwick’s script shows some of the power of R for doing more than statistics. Mac users might be interested in Ben Schmidt’s tutorial ‘Command-line OCR on a Mac’ from his digital history graduate seminar at Northeastern University, online athttp://benschmidt.org/dighist13/?page_id=129.


출처 : Extracting Text from PDFs; Doing OCR; all within R


바로 : 요즘은 PDF에서 곧장 텍스트를 추출할 수 있다. 그러나 다양한 이유로 텍스트 추출이 어려운 경우가 있다. 물론 이를 지원하는 수 많은 유료소프트웨어가 있기는 하지만......돈 없는 우리가 불법행위를 하지 않으면서 텍스트를 추출하는 방법은 무엇인가?! 저자는 무료툴인 R을 통해서 텍스트를 추출하는 방법에 대해서 서술하고 있다. 

가칭 "한국 역사 관계 데이터베이스(Korea Historical Network DataBase, KHNDB)"


본 내용은 한국 역사에서 출현하는 관계를 데이터베이스화 하기 위한 기초작업이다. 관계는 인물, 기관, 사물 등 다양한 영역의 관계를 의미한다. 그러나 역량의 한계로 우선적으로 특정 DB들을 바탕으로 인물관계 데이터베이스만 구축 시도한다.(그래도 10만건……혼자서 10만건 하려니 죽을 거 같…-_)


아래의 규칙들은 추후 수정될 수도 있다.

혹시 괜찮은 아이디어나 관련 정보가 있으시면 언제든지....조언 좀..ㅠㅠ

 


+ 인물 ID 값 규칙

예시 : 1가귀U9999X0

남녀구별 : 남자(1), 여자(2), 혼합(3), 미상(9)

한글이름 :  이름(가귀) 명시. 3자리 이상의 이름도 모두 서술

보조연도 : B(생년) or D(몰년) or U(미상) B1545 : 생년(Birth) 1545년을 의미, 몰년일 경우 D와 서기연도, 생몰년 미상일 경우 U9999가 옴

X0 : 중복되는 인물이 있을 경우 X1, X2로 증가. X9는 기존DB에 없는 것을 표기

 


 


+ 사회관계 ID값 규칙

예시 : S0101

사회관계고유값 : S(society)

분류코드값 : 분류코드표 참조

ID

한국어

영어

중국어

S0100

사회관계(포괄)

Associations (General)

社會關係籠統

S0101

사회관계(포괄)

Associations (General)

社會關係籠統

S0102

모두 X 구성원

Association through common membership

……之成員

S0103

사회교제

Social Interactions

社會交際

S0200

학술관계류

Scholarship

學術關係類

S0201

학술(포괄)

Scholarship (General)

學術籠統

S0202

사도관계(스승)

Teacher-Student

師生關係

S0203

사도관계(제자)

Teacher-Student

師生關係

S0204

학술교류

Intellectual Affiliations

學術交往

S0205

학술주제밀접

Association by Scholarly Topic

學術主題相近

S0206

모두 X 구성원

Association through common membership

……之成員

S0207

학술원조

Academic Patronage

學術襄助

S0208

문학예술교류

Literary and Artistic Affiliations

文學藝術交往

S0209

학술비판

Intellectual Attacks

學術攻訐

S0300

친구관계류

Friendship

朋友關係類

S0301

친구관계(포괄)

Friendship(General)

朋友關係籠統

S0400

정치관계류

Politics

政治關係類

S0401

정치관계(포괄)

Politics (General)

政治關係籠統

S0402

관직관계(동급)

Connection via office (equal)

官場關係平級

S0403

관직관계(부하)

Connection via office (subordinate)

官場關係下屬

S0404

관직관계(상사)

Connection via office (superior)

官場關係上司

S0405

정치원조

Supportive political association

政治奧援

S0406

천거보증

Recommendation and sponsorship

舉保

S0407

정치대항

Oppositional political association

政治對抗

S0500

저술관계류

Writings

著述關係類

S0501

저술관계(포괄)

Writings (General)

著述關係籠統

S0502

일반문장

Commemorative Texts

記詠文字

S0503

묘지문장

Epitaphs

墓誌文字

S0504

서발문문장

Prefaces/Postfaces

序跋文字

S0505

예의문장

Ritual Texts

禮儀文字

S0506

전기문장

Biographical Texts

傳記文字

S0507

논설문장

Explanatory Texts

論說文字

S0508

모토문장

Mottos

箴銘文字

S0509

서찰문장

Correspondences

書札文字

S0510

계약(보상)문장

Occasional Texts

應酬文字

S0600

군사관계류

Military

軍事關係類

S0601

군사관계(포괄)

Military (General)

軍事關係籠統

S0602

군사지원

Supportive military association

軍事支持

S0603

군사대항

Oppositional military association

軍事對抗

S0700

의료관계류

Medicine

醫療關係類

S0701

의료관계(포괄)

Medicine (General)

醫療關係籠統

S0800

종교관계류

Religion

教關係

S0801

종교관계(포괄)

Religion (General)

教關係籠統

S0900

가정관계류

Family

家庭關係類

S0901

가정관계(포괄)

Family (General)

家庭關係籠統

S1000

재정관계류

Finance

財務關係類

S1001

재정관계(포괄)

Finance (General)

財務關係籠統

S1100

예술관계류

 

 

S1101

예술관계(포괄)

 

 

 


 






+ 혈연관계 ID값 규칙

B0201_0302

혈연관계 고유값 : B

촌수 : 01, 02, 03 (단순촌수계산. 법도무시)

관계속성(상하위) : 0(통합), 1(상위) 2(동급) 3(하위)

관계속성(구분) : 무속성(0) 친계(1) 외계(2) 부당계(3) 처당계(4)

구분자 : _

남녀구별 : 통합(0), 남자(1), 여자(2)

고유값 : 3자리


사실 위의 규칙으로 확장시 1000개정도는 무난히 넘을 것이다. 일단 몇 개만 예시로 제시한 것일 뿐이다. CBDB의 혈연코드가 559개였는데, 본인이 4촌이하 주요정보만 대략 했는데도 170여개이다. 만약 본인이 마음만 먹으면 정말 1000개 만들수도 있다. 하지만 실제로 그런 관계가 문헌이나 자료에 명시된 경우는 거의 없기에 사실상 아래 코드로 90%이상 커버 가능하다고 본다. 

 

코드

설명

B9999_9999

미상

B0000_0000

친척

B0000_0100

姻親(통합)

B0000_0200

親族

B0000_0300

親屬

B0000_0400

直系親族

B0001_0000

直系血族

B0011_0000

直系尊屬

B0031_0000

直系卑屬

B0003_0000

부당(夫黨)

B0004_0000

처당(妻黨)

B0020_0000

부부(통합)

B0020_1000

丈夫(통합)

B0020_1001

未婚夫

B0020_1051

第二任丈夫

B0020_1052

第三任丈夫

B0020_2000

妻子(통합)

B0020_2001

未婚妻

B0020_2010

B0110_0000

부모(통합)

B0110_1000

(통합)

B0110_1001

生父

B0110_1002

養父

B0110_1003

繼父

B0110_1004

嗣父

B0110_2000

(통합)

B0110_2001

生母

B0110_2002

養母

B0110_2003

繼母

B0110_2004

嗣母

B0110_2005

乳母,유모

B0114_0000

장인-장모(통합)

B0114_1000

장인

B0114_2000

장모

B0113_0000

시아버지-시어머니

B0113_1000

시아버지(시부)

B0113_2000

시어머니(시모)

B0130_0000

자식(통합)

B0130_1000

아들(통합)

B0130_1001

獨子

B0130_1002

繼子

B0130_1003

養子(非嗣子)

B0130_1004

庶子

B0130_1005

私生子

B0130_1101

長子; 第一子

B0130_1102

次子

B0130_1103

三子

B0130_1104

四子

B0130_1105

五子

B0130_1106

六子

B0130_1107

七子

B0130_1108

八子

B0130_1109

九子

B0130_2000

(통합)

B0130_2001

獨女

B0130_2002

繼女

B0130_2003

養女(非嗣女)

B0130_2004

庶女

B0130_2005

私生女

B0130_2101

長女; 第一女

B0130_2102

次女

B0130_2103

三女

B0130_2104

四女

B0130_2105

五女

B0130_2106

六女

B0130_2107

七女

B0130_2108

八女

B0130_2109

九女

B0211_0000

조부모

B0211_1000

할아버지

B0211_2000

할머니

B0212_0000

외조부모

B0212_1000

외할아버지

B0212_2000

외할머니

B0214_0000

처조부모

B0214_1000

처조부

B0214_2000

처조모

B0213_0000

부조부모

B0213_1000

부조부

B0213_2000

부조모

B0220_0000

형제-자매

B0220_1000

(오빠)

B0220_2000

(오빠)의 처

B0220_2100

누나(언니)

B0200_1100

누나(언니의) 남편

B0220_1200

남동생

B0220_2200

남동생의 처

B0220_2300

여동생

B0220_1300

여동생의 남편

B0224_0000

처의 형제-자매

B0224_1000

처의 형(오빠)

B0224_2000

처의 형(오빠)의 처

B0224_2100

처의 누나(언니)

B0204_1100

처의 누나(언니의) 남편

B0224_1200

처의 남동생

B0224_2200

처의 남동생의 처

B0224_2300

처의 여동생

B0224_1300

처의 여동생의 남편

B0223_0000

남편의 형제-자매

B0223_1000

남편의 형(오빠)

B0223_2000

남편의 형(오빠)의 처

B0223_2100

남편의 누나(언니)

B0203_1100

남편의 누나(언니의) 남편

B0223_1200

남편의 남동생

B0223_2200

남편의 남동생의 처

B0223_2300

남편의 여동생

B0223_1300

남편의 여동생의 남편

B0230_0000

손자-손녀

B0230_1000

손자

B0230_2000

손자의 처

B0230_2100

손녀

B0230_1100

손녀의 남편

B0311_0000

증조부모

B0311_1000

증조부

B0311_2000

증조모

B0312_0000

외증조부

B0312_1000

외증조부

B0312_2000

외증조모

B0314_0000

처증조부모

B0314_1000

처증조부

B0314_2000

처증조모

B0313_0000

부증조부모

B0313_1000

부증조부

B0313_2000

부증조모

B0311_0100

삼촌-고모-

B0311_1100

삼촌

B0311_2100

삼촌의 처

B0311_1110

백부(큰아버지)

B0311_2110

백모(큰아버지의 처)

B0311_1120

숙부(작은아버지)

B0311_2120

숙모(작은아버지의 처)

B0311_2150

고모

B0311_1150

고모의 남편

B0311_2160

큰고모

B0311_1160

큰고모의 남편

B0311_2170

작은고모

B0311_1170

작은고모의 남편

B0312_0200

외숙-이모-

B0312_1200

외숙

B0312_2200

외숙의 처

B0312_2150

이모

B0312_1150

이모의 남편

B0314_0100

처고모부-처숙부-

B0314_1100

처고모부

B0314_2100

처고모부의 처

B0314_2150

처고모

B0314_1150

처고모의 남편

B0313_0100

부고모부-부숙부-

B0313_1100

부고모부

B0313_2100

부고모부의 처

B0313_2150

부고모

B0313_1150

부고모의 남편

B0331_0100

-생질-

B0331_1100

B0331_1200

질의 처

B0331_2150

생질

B0331_1150

생질의 처

B0411_0000

고조부모

B0411_1000

고조부

B0411_2000

고조모

B0412_0000

사촌

B0412_1000

남자사촌

B0412_2000

여자사촌

B0412_0100

종형제

B0412_1100

남자종형제

B0412_2100

여자종형제

B0412_0200

내종형제

B0412_1200

남자내종형제

B0412_2200

여자내종형제

B1001_1000

대부(大父)

B1001_1100

족숙(族叔)

B1002_1000

족형(族兄)

B1002_1100

족제(族弟)

B1003_1000

족질(族姪)

B9900_1000

종씨(宗氏), 존장(尊長)

 


 






+ XML 문서 설계

최대한 단순화 시켰다. 사실 복잡하게 하는게 더 이상하다. 

문제는 어떤 관계인지 판단해서 추가해주는 것이...일이지. ㅠㅠ 아우..ㅠㅠ




DTD

<?xml version="1.0" encoding="UTF-8"?>

<?generated by 바로-Baro-把路 ddokbaro.com  ddokbaro@gmail.com (2014.01.10)?>

<?Korea Historical Network DataBase?>

 

<!ELEMENT KHNDB ((인물+))>

<?우선 인물만 네트워킹 작업을 하고 추후 기관, 관직 등을 추가?>

 

<!ELEMENT 인물 ((관계정보))>

<!ATTLIST 인물   id CDATA #REQUIRED>

 

<!ELEMENT 관계정보 ((관계*))>

 

<!ELEMENT 관계 (#PCDATA)>

<!ATTLIST 관계   유형 CDATA #REQUIRED>

 

 

XML 예시

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE KHNDB SYSTEM "KHNDB.dtd">

<?generated by 바로-Baro-把路 ddokbaro.com  ddokbaro@gmail.com (2014.01.10)?>

<?Korea Historical Network DataBase?>

<?대상 인물 : 98140......어느 세월에 하나?>

 

<KHNDB>

             <인물 id="가귀U9999X0">

                           <관계정보>

                                        <관계 유형="S202">승전U9999X0</관계>

                           </관계정보>

             </인물>

             <인물 id="가루U9999X0">

                           <관계정보>

                                        <관계 유형="S404">안승U9999X0</관계>

                           </관계정보>

             </인물>

             <인물 id="가마U9999X0">

                           <관계정보>

                                        <관계 유형="S0401">아탁득문U9999X0</관계>

                                        <관계 유형="S0401">奇非U9999X9</관계>

                                        <관계 유형="S0401">欽明王U9999X9</관계>

                                        <관계 유형="S0401">眞慕宣文U9999X9</관계>

                           </관계정보>

             </인물>

             <인물 id="가실U9999X0">

                           <관계정보>

                                        <관계 유형="B0020_2000">설씨녀U9999X0</관계>

                           </관계정보>

             </인물>

             <인물 id="가실왕U9999X0">

                           <관계정보>

                                        <관계 유형="S0403">우륵U9999X0</관계>

                                        <관계 유형="S0111">우륵U9999X0</관계>

                                        <관계 유형="S0407">진흥왕U9999X9</관계>

                                        <관계 유형="S0603">진흥왕U9999X9</관계>

                           </관계정보>

             </인물>

             <인물 id="가안책B1559X0">

                           <관계정보>

                                        <관계 유형="B0110_1000">賈忠權U9999X9</관계>

                                        <관계 유형="B0220_1200">賈安術U9999X9</관계>

                           </관계정보>

             </인물>

             <인물 id="가안책B1559X0">

                           <관계정보>

                                        <관계 유형="S0404">부여융B0615X0</관계>

                                        <관계 유형="S0603">蘇定方U9999X9</관계>

                           </관계정보>

             </인물>

</KHNDB>

 

 

 

 

  1. 충구리 2014.01.13 18:31

    수고많으십니다.^^
    DB 다루는 일이 전공이 아님에도 정말 노력 많이 하시네요. 대단합니다.^^
    혹시나 도움이 될까해서 의견 드립니다.
    우선, 하시는 작업을 보아하니.. '정규화' 관련된 내용을 필히 아셔야할 거 같습니다.
    꼭 그런것은 아니나 속성이라는 것은 하나의 의미를 갖고있는게 좋습니다.
    위에 정의한 id의 값에 여러가지 의미가 있다는것은 추후 데이타 관리 및 검색에서 큰 도움이 되질 못합니다.
    암튼.. 나중에 좋은 DB가 완성되길 기원합니다.^^

    • Favicon of https://www.ddokbaro.com BlogIcon 바로바로 2014.01.14 10:35 신고

      조언 감사드립니다. 무슨 말씀이신지는 대충이나마 알겠습니다. 그러나 XML과 RDB를 혼동하신것은 아닐까 싶습니다. 해당 사항은 XML을 통해서 메타데이터를 작성하는 것을 원칙으로 합니다. 그 이후 RDB가 필요하다면 XML로 된 메타데이터에서 추출하여 정규화를 진행하는 방식입니다. 고로 XML 원데이터에서 ID속성값이 다양한 의미를 가지게 만드는 것이 추후 다양한 정보를 다양한 형식으로 정규화하기 유리합니다.

      물론 최초부터 RDB 베이스로 진행할 생각을 하며 ID값을 부여한다면 ID값에 여러가지 의미를 담는것보다 그냥 다양한 속성에 대한 정규화를 진행하는 것이 더 효율적이겠지요. 하지만 학술연구에서는 RDB보다는 XML을 기반으로 다양한 형식과 가능성을 지원하는 것이 더 유리하기에 메타데이터를 XML형식으로 정한 것이고, ID값에 다양한 의미를 담은 것입니다.

      사실 위에 있는 ID값 규칙도 완성은 아니고, 추후 다양한 학술적인 요구에 대응하기 위한 주요요소가 무엇인지 끊임없이 고민하고 있습니다.

      좋은 의견 있으시면 언제든지 말씀해주시기 바랍니다^^

  2. 충구리 2014.01.14 11:58

    네.. 그런 속뜻이 있었군요...^^
    XML 작성시 XML전용 편집툴을 이용하고 있는거죠? 나중에 그 데이터 양이 많아질 경우,
    자료입력 및 편집에 대한 걱정이 앞서다보니, 제가 노파심에 RDB를 언급했나 봅니다.
    암튼.. 추후 DB화의 어려움없도록 XML이 잘 작성되길 기대합니다.
    수고하세요~


    • Favicon of https://www.ddokbaro.com BlogIcon 바로바로 2014.01.14 13:28 신고

      자료입력부분 때문에라도 저렇게 해놓은 것이랍니다. ㅠㅠ 많은 자료를 혼자 입력해야되서...ㅠㅠ 하아..ㅠㅠ(괜히 XML 어트리뷰트에 다양한 정보를 입력하라고 해버리면 작업시간만 증가. 그냥 규칙을 정하고 하나로 압축)

      기왕 입력하는거 단순ID가 아닌 유의미한 ID로 입력해서 나중에 추출하자라는 발상이랍니다. 10만건. 그것도 컴퓨터로 처리 불가능한 관계 분석작업을 하면서 데이터 입력. 하아....정말 이런건 정식 프로젝트로 해야겠지만, 정식 프로젝트가 되려면 일정한 성과를 보여야 된다는 딜레마이지요.

      하아...일단 어떻게 하는것이 가장 효율적인것인가 고민하고 있습니다. 이러다가 결국 전용입력프로그램을 만들어야된다는 결론이 나오면...위의 규칙을 적용해서 RDB로 재해석하면 되겠지요. 하지만...전용프로그램을 만들어도...효율이 오를런지...어차피 분석작업이 시간이 걸리는거라서....여러사람이 동시에 진행할 계획이라면 전용프로그램으로 RDB와 연동시키기는 것이 좋겠지만...저 혼자 해야됩니다. 뭐든지 하는 연구생-_-!

DTD(문서 형식 정의(Document Type Definition)는 컴퓨터 용어로, SGML 계열의 마크업 언어에서 문서 형식을 정의하는 것이다. SGML을 비롯해 HTML, XHTML, XML 따위에서 쓰인다. XML DTD는 XML 문서의 구조를 정의한다. 다시 말해서 Valid XML 문서가 되기 위해 문서 내에 어떤 요소를 사용하고, 요소간의 계층구조를 기술하고, 요소의 내용으로 올 수 있는 내용을 정의한다.


DTD는 문법이 간단하며, SGML 계열에서 사용되어 왔기에 기존의 다양한 문서 정의가 DTD로 되어 있다. 그러나 DTD가 가지고 있는 XML에서의 다양한 확장의 한계로 인하여 XML_Schema 표준을 사용할 것을 추천한다.



1. DTD 선언 방식

1.1. 외부 DTD 선언

<?xml version="1.0" ending="utf-8"?>

<!DOCTYPE 루트요소이름 SYSTEM "DTD문서경로">


SYSTEM : 시스템에 존재하는 물리적인 위치정보. 파일이름 or 특정URL

<!DOCTYPE CONCEPT SYSTEM "concept.dtd">

<!DOCTYPE CONCEPT SYSTEM "http://ddokbaro.tistory.com/xml/concept.dtd">

<!DOCTYPE CONCEPT SYSTEM "file:///c:/concept.dtd">


PUBLIC : 특수한 형태를 식별자를 사용하여 외부DTD 참조

<!DOCTYPE member PUBLIC "-//W3C/DTD XHTML 1.0 Strict//EN" >


혼합방식 : SYSTEM  + PUBLIC 

<!DOCTYPE CONCEPT PUBLIC "-//W3C/DTD XHTML 1.0 Strict//EN" "http://ddokbaro.tistory.com/xml/concept.dtd" >


1.2. 내부 DTD 선언 - 실무에서 쓸일 없음.

1.3. 외부-내부 DTD 선언 - 실무에서 쓸일 없음. 




2. ELEMENT

2.1. ELEMENT 정의 형태

#PCDATA(문자 데이터) : <!ELEMENT ele-name (#PCDATA)>

자식요소 : <!ELEMENT ele-name (ele-name+, ele-name, ....)+>

자식요소와 문자 데이터의 혼합 : <!ELEMENT ele-name (#PCDATA | ele-name ....)*>

EMPTY(빈 content) : <!ELEMENT ele-name EMPTY>

ANY(위의 4가지가