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>

 

 

 

 

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가지가 모두 오는 경우) : <!ELEMENT ele-name ANY>


2.2. 출연횟수 정의


?

 0 or 1 (출현하지 않거나 1번만 출현)

 0개 이상 출현(출현하지 않거나 반복 출현가능)

+

 1개 이상 출현(무조건 1번은 출현해야되고, 여러번 반복 출현 가능)


2.3. #PCDATA(문자 데이터)

- PCDATA : Parsed Character Data 

- 출현횟수 정의 불가 : <!ELEMENT name (#PCDATA)+>  (X)


2.4. 자식요소

<!ELEMENT CONCEPT (time, place)> 

<!ELEMENT PEOPLE ( (Mr|Ms), Firstname, Middlename*, Lastname) >

<!ELEMENT PEOPLE ( email*, ( homePhone | officePhone | mobilePhone)+, address?) > 


2.5. #PCDATA + 자식요소

<!ELEMENT 요소이름 (#PCDATA|요소명1|요소명2.....)*>

#PCDATA는 반드시 자식요소보다 먼저 와야 한다.

- "|" 이외의 출현횟수나 출현방법은 괄호 밖에 정의한다.


2.6. EMPTY - 빈요소, 실무에서 사용빈도 적음

<!ELEMENT 요소명 EMPTY>


2.7. ANY - 모든사항 허용, 최대한 사용하지 말 것

<!ELEMENT 요소명 ANY>




3. Attribute

3.1. 기본형식

<!ATTLIST ele-name (att-name type default-decl)+>


ele-name : 속성이 포함될 요소의 이름

att-name : 요소 안에 포함될 속성의 이름

type : 속성값을 제한하기 위한 값으로 10가지 속성타입이 올 수 있다.

default-decl : 속성이 요소에 반드시 포함되어야 하는지 등의 특별한 제한을 두기 위하여 사용된다. => #IMPLIED, #REQUIRED, 기본값, #FIXED


3.2. att-name

- 문자 시작, 숫자 시작 불가, 공백불가, "_", ":"로 시작가능


3.3. type

 CDATA 

 문자데이터(단순한 텍스트 문자열) 

 열거형 

 속성값은 반드시 DTD에 명시적으로 정의된 일련의 값들 중의 하나가 되어야 한다. 

 ID 

 속성값은 해당 요소에서 고유한 식별자이다. 이것은 반드시 모든 XML 이름 규칙을 따르는 텍스트 문자열 이어야 한다.

 IDREF 

 IDREF의 값과 똑같은 ID 값을 갖고 있는 요소에 대한 참조 값 

 IDREFS 

 공백에 의해 경계가 나뉘는 IDREF들의 리스트 

 NMTOKEN 

 하나의 이름 토큰 - XML 이름 규칙을 따르는 텍스트 문자열 

 NMTOKENS 

 공백에 의해 경계가 나뉘는 NMTOKEN들의 리스트 

 ENTITY

 이미 정의된 ENTITY의 이름 

 ENTITIES 

 공백에 의해 경계가 나뉘는 ENTITY 이름들의 리스트 

 NOTATION

 속성값은 DTD에 명시적으로 선언된 NOTATION type이 되어야 한다. 


<!ATTLIST ele-name att-name CDATA default-decl >

<!ATTLIST elel-name att-name (value1 | value2 | .. ) default-decl >

<!ATTLIST ele-name att-name ID (#REQUIRED|#IMPLIED)>

<!ATTLIST ele-name att-name IDREF(S) default-decl>

<!ATTLIST ele-name att-name NMTOKEN(S) default-decl >



3.4. default-decl

#REQUIRED

 속성은 반드시 요소에서 사용되어야 한다. 

#IMPLIED   속성 사용이 선택적이며, 만일 사용하지 않으면 요소는 이 속성을 갖지 않는다. 기본 값은 줄 수없다. 

 #FIXED

 속성 사용은 선택적이고, 사용하지 않으면 고정 값을 기본 값으로 가지며 사용할 경우, "고정 값"을 속성 값으로 가진다. 즉 상수와 동일하다. 




4. ENTITY

- 반복적으로 사용되는 문장이나 문자열을 참조

XML조각, DTD조각, 긴 문자열, 상수, non-XML 데이터 사용가능

- 세부사항 참조 링크




5.