3. Ⅰ. DOM이란
▣ DOM(Document Object Model) 이란?
1. 문서를 객체로 표현하기 위한 표준으로서 HTML이나 XML등의 문서를 객체로
표현할 때 사용 하는 API 이다.
2. 문서의 객체 모델(Document Object Model)은 HTML내에 들어 있는 요소를
구조화 객체 모델로 표현 하는 양식이다.
3. DOM은 HTML과 XML문서에 대하여, 이들 문서의 구조적인 표현방법을 제공하며
어떻게 하면 스크립트를 이용하여 이러한 구조에 접근할 수 있는지를 정의하는
API 이다.
▣ 문서를 트리로 표현하기
- HTML 문서는 중첩된 태그로 구성된 계층적인 구조를 이며, 이는 DOM에서
객체 트리로 표현된다.
- DOM 트리에는 HTML 태그나 엘리먼트를 나타내는 노드가 담긴다.
▣ 토큰화
- 전달 받은 HTML 문서(Source)에 대하여 Char 단위로 해석 토큰화 처리를 진행한다.
4. Ⅰ. DOM 개요
< HTML5 spec에 명시된 HTML parsing model 개념도>
HTMLTokenizer
<html>
<head>
<title>simple HTML</title>
</head>
<body>
<div>
<p>This is for seminar.</p>
</div>
</body>
</html>
?
HTMLTreeBuilder
7. 1. 동작 메커니즘 분석 - 소스분석
HTMLDocumentParser.cpp
void HTMLDocumentParser::pumpTokenizer(SynchronousMode mode)
{
...
PumpSession session(m_pumpSessionNestingLevel, contextForParsingSession());
while (canTakeNextToken(mode, session) && !session.needsYield) {
…
if (!m_tokenizer->nextToken(m_input.current(), token()))
break;
…
}
constructTreeFromHTMLToken(token());
ASSERT(token().isUninitialized());
}
...
}
저장된 soruce 내용의 끝까지 반복한다!!!
“bool HTMLTokenizer::nextToken(SegmentedString& source, HTMLToken& token) “
: DOM Tree 구성에 필요한 자료(태그 이름, 속성 이름, 속성 값 등)를 소스로 부터 추출한다.
“void HTMLDocumentParser::constructTreeFromHTMLToken(HTMLToken& rawToken)”
: 추출한 자료를 이용하여 DOM Tree를 구성한다.
8. 1. 동작 메커니즘 분석 - 소스분석
HTMLTokenizer.cpp
bool HTMLTokenizer::nextToken(SegmentedString& source, HTMLToken& token)
{
...
m_token = &token;
if (!m_bufferedEndTagName.isEmpty() && !isEndTagBufferingState(m_state)) {
m_token->beginEndTag(m_bufferedEndTagName);
m_bufferedEndTagName.clear();
m_appropriateEndTagName.clear();
m_temporaryBuffer.clear();
if (m_state == HTMLTokenizer::DataState) {
return true;
}
}
...
if (source.isEmpty() || !m_inputStreamPreprocessor.peek(source))
return haveBufferedCharacterToken();
UChar cc = m_inputStreamPreprocessor.nextInputCharacter();
switch (m_state) {
...
}
}
InputStreamPreprocessor.h
ALWAYS_INLINE bool peek(SegmentedString& source)
{
m_nextInputCharacter = source.currentChar();
static const UChar specialCharacterMask = 'n' | 'r' | '0';
if (m_nextInputCharacter & ~specialCharacterMask) {
m_skipNextNewLine = false;
return true;
}
return processNextInputCharacter(source);
}
Source의 character 하나를 가지고 온다!!!
Type을 갖을 수 있는 최소 단위의 token이
될 때까지 순회한다!!!
9. 1. 동작 메커니즘 분석 - 소스분석
HTMLTokenizer.cpp
bool HTMLTokenizer::nextToken(SegmentedString& source, HTMLToken& token)
{
…
switch (m_state) {
HTML_BEGIN_STATE(DataState) {
…
else if (cc == '<') {
if (m_token->type() == HTMLToken::Character) {
return true;
}
HTML_ADVANCE_TO(TagOpenState);
…
}
END_STATE()
…
}
HTML_ADVANCE_TO(…)
#define ADVANCE_TO(prefix, stateName)
do {
m_state = prefix::stateName;
if (!m_inputStreamPreprocessor.advance(source))
return haveBufferedCharacterToken();
cc = m_inputStreamPreprocessor.nextInputCharacter();
goto stateName;
} while (false)
HTML_BEGIN_STATE(…) END_STATE()
#define BEGIN_STATE(prefix, stateName) case prefix::stateName:
stateName:
#define END_STATE() ASSERT_NOT_REACHED(); break;
- 71가지의 State로 구성되어 있음.
- goto 문을 이용해서 해당상태에서 다음 상태로 이동함.
- DOM Tree 자료로서 의미 있는 token이 이루어질 때까지 Character를
하나씩 받아서 반복 수행함.
- DOM Tree 구성을 위한 token에 관한 type을 정의함.
Source에서 다음 character 하나를 가지고 온다!!!
10. 1. 동작 메커니즘 분석 – nextToken 순회 알고리즘
DataState
TagOpenState
TagNameState
BeforeAttributeName
State
AttributeName
State
AfterAttributeName
State
BeforAttributeValue
State
AttributeValue
SingleQuote
State
AttributeValue
DoubleQuote
State
AfterAttributeValue
QuoteState
(1) DataState - “ < “ 문자를 확인.
(2) TagOpenState – m_type을 StartTag로 변경.
(3) TagNameState – TagnName을 m_data에 저장하고, 공백인지 확인.
(4) BeforeAttributeNameState – m_currentAttribute.에 입력 준비함.
(5) AttributeNameState – m_currentAttribute.name에 AttributeName을 입
력함. 공백인지 확인.
(6) AfterAttributeNameState - “ = “ 문자확인.
(7) BeforAttributeValueState - 큰따옴표 또는 작은따옴표 문자인지 확인.
(8-1) AttributeValueDoubleQuoteState - 큰따옴표이면
m_currentAttribute .value에 AttributeValue을 저장하고, 큰따옴표 문자확인.
(8-2) AttributeValueSingleQuoteState - 작은따옴표 이면
m_currentAttribute .value에 AttributeValue을 저장하고, 작은따옴표 문자확인.
(9) AfterAttributeValueQuoteState – “ > “ 문자를 확인하고 goto문 순회를
마침.
DataState를 제외한 위의 모든 경우 “>”문자를 확인하면 goto문 순회를 마침.
< StartTag >
11. 1. 동작 메커니즘 분석 – nextToken 순회 알고리즘
DataState
TagOpenState
EndTagOpenState
TagNameState
(1) DataState - “ < “ 문자를 확인.
(2) TagOpenState – “ / “ 문자를 확인.
(3) EndTagOpenState – m_type을 EndTag로 변경
(4) TagNameState – TagnName을 m_data에 저장하고, “ > “ 문자를 확인하고
goto문 순회를 마침.
DataState를 제외한 위의 모든 경우 “>”문자를 확인하면 goto문 순회를 마침.
< EndTag >
< Comment >
DataState
TagOpenState
MarkupDeclaration
OpenState
CommentStartState
CommentEndDashState
CommentEndState
(1) DataState - “ < “ 문자를 확인.
(2) TagOpenState – “ ! “ 문자를 확인.
(3) MarkupDeclarationOpenState – “--“ 문자를 확인하고 m_type을
Comment로 변경.
(4) CommentStartState – Comment를 m_data에 저장.
(5) CommentEndDashState – “-”를 확인.
(6) CommentEndState - “ > “ 문자를 확인하고 goto문 순회를 마침.
DataStated와 CommentEndDashState를 제외한 위의 모든 경우 “>”문자를 확
인하면 goto문 순회를 마침.
15. while ( … ) {
︙
if (!m_tokenizer->nextToken(m_input.current(), token()))
break;
︙
constructTreeFromHTMLToken (token());
}
HTMLDocumentParser::pumpTokenizer (…)
하나의 token 완성됨.
하나의 token이 생성되면 이를 Tree 구조에 포함한다.
HTMLTreeBuilder::constructTree (token)
switch (token->type()) {
︙
case HTMLToken::DOCTYPE:
processDoctypeToken(token);
case HTMLToken::StartTag:
processStartTag(token);
case HTMLToken::EndTag:
processEndTag(token);
case HTMLToken::Comment:
processComment(token);
case HTMLToken::Character:
processCharacter(token);
case HTMLToken::EndOfFile:
processEndOfFile(token);
}
HTMLTreeBuilder::processToken(AtomicHTMLToken* token)
token의 type에 따라 각각의 process 함수를 호출.
2. Dom Tree 구축
17. 2. Dom Tree 구축
InitialMode
AfterAfterBodyMode
BeforeHTMLMode
AfterBodyMode
BeforeHeadMode
InBodyMode
AfterHeadMode
InHeadMode
Html 토큰
파일 끝 토큰
DocType 토큰
Head tag 토큰
Head 종료 토큰
Body 토큰
Body 종료 토큰
insertionMode에 따라
각각의 처리 수행
HTML 종료 토큰
<!DCOTYPE html>
<html>
<head>
</head>
<body>
</body>
</html>
18. 2. Dom Tree 구축
HTML
HEAD
TITLE
text
BODY
DIV
P
text
IMG
insertHTMLHtmlStartTagBeforeHTML
insertHTMLHeadElement
insertHTMLElement
insertTextNode
insertHTMLBodyElement
insertHTMLElement
insertHTMLElement
insertTextNode
insertSelfCloseingHTMLElement
HTMLConstructionSite class
HTML
HEAD
TITLE
text
BODY
DIV
P
text
P
text
<html>
<head>
<title>simple HTML</title>
</head>
<body>
<div>
<p>simple</p>
<p>html</p>
</div>
</body>
</html>
20. RefPtr<HTMLHtmlElement> element = HTMLHtmlElement::create (token);
︙
attachLater (m_attachmentRoot, element);
m_openElements.pushHTMLHtmlElement (HTMLStackItem::create (element, token));
executeQueuedTasks ();
︙
void HTMLConstructionSite::insertHTMLElement (AtomicHTMLToken* token)
각각의 parent node와 child node로 묶어
서 m_attachmentQueue에 append
m_attachmentRoot
HTMLElement (htmlTag)
2. Dom Tree 구축
HTMLElement(htmlTag) 객체 생성.
m_stackDepth++;
m_top = adoptPtr(new ElementRecord(item, m_top.release()));
void HTMLElementStack::pushCommon(PassRefPtr<HTMLStackItem> item)
void pushHTMLHtmlElement(PassRefPtr<HTMLStackItem>)
HTML
void HTMLElementStack::pushRootNodeCommon(…)
m_top
21. ② Html
m_document : ①
m_firstChild : ③
m_lastChild : ④
③ Head
parent : ②
m_next : ④
m_firstChild : ⑤
④ Body
parent : ②
m_previous : ③
m_firstChild : ⑦
⑥ Text
data : Simple
① Document
m_firstChild : ②
① Document
② Html
<html>
<head>
<title> Simple</title>
</head>
<body>
Hello, World!
</body>
</html>
⑤ Title
m_parent : ③
m_firstChild : ⑥
⑦ Text
data : Hello,World!
Head Body
Title ⑦ Text
⑥ Text
③ Head ④ Body
⑤ Title
①
②
⑤
⑥
④
⑦
③
자료구조 DOM Tree
HTML
2. Dom Tree 구축
24. HTMLElement (htmlTag)
HTMLElement (headTag)
m_head = HTMLStackItem::create(createHTMLElement(token), token);
attachLater (currentNode(), m_head->element());
m_openElements.pushHTMLHeadElement (m_head);
insertHTMLHeadElement (AtomicHTMLToken* token)
m_openElements stack topNode인 currentNode()가 parent,
head element가 child node
HEAD
HTML
HEAD
HTML
TITLE
HTMLElement (headTag)
HTMLElement (titleTag)
title tag 처리
3. 소스분석 – <Head> tag / <Title> tag 처리
︙
m_originalInsertionMode = m_insertionMode;
setInsertionMode(TextMode);
insertHTMLHeadElement (AtomicHTMLToken* token)
m_top
m_top
25. HTMLTreeBuilder.cpp
void HTMLTreeBuilder::processToken(AtomicHTMLToken* token)
void
HTMLTreeBuilder::processCharacter(AtomicHTMLToken&
token)
{
ExternalCharacterTokenBuffer buffer(token);
processCharacterBuffer(buffer);
}
HTMLTreeBuilder.cpp
void HTMLTreeBuilder::processStartTag(AtomicHTMLToken* token)
{
switch (insertionMode()) {
….
case TextMode:
if (token->name() == htmlTag) {
m_tree.insertTextNode(buffer.takeRemaining());
break;
}
}
HTMLConstructionSite.cpp
void HTMLConstructionSite::insertHTMLHtmlStartTagBeforeHTML(AtomicHTMLToken* token)
{
HTMLConstructionSiteTask task;
task.parent = currentNode();
…
while(currentPosition < characters.length())
{
textNode = Text::create(…);
}
task.child = textNode.release();
executeTask(task);
}
3. 소스분석 – <Text> 처리
HTML
HEAD
TITLE
text
26. 3. 소스분석 – </Title> tag 처리
HTMLElementStack.cpp
void HTMLElementStack::popCommon()
{
top()->finishParsingChildren();
m_top = m_top->releaseNext();
m_stackDepth--;
}
HTMLTreeBuilder.cpp
void HTMLTreeBuilder::processToken(AtomicHTMLToken* token)
switch (token->type()) {
case HTMLToken::Uninitialized:
….
case HTMLToken::EndTag::
processEndTag (token);
….
}
HTMLTreeBuilder.cpp
void HTMLTreeBuilder::processCharacter (AtomicHTMLToken* token)
{
switch (insertionMode()) {
….
case HTMLToken::EndTag:
….
case TextMode:
…
m_tree.openElements()->pop();
setInsertionMode(m_originalInsertionMode);
break;
}
}
HTMLElementStack.cpp
void HTMLElementStack::popHTMLHeadElement()
{
popCommon();
}
HTMLElementStack.cpp
void HTML####Element::finishParsingChildren()
{
…
HTMLElement::finishParsingChildren();
} ※ 각 해당하는 Element(img, head …)의 finishParsingChildren() 가 호출 된다
HEAD
HTML
TITLE
m_top
27. switch (insertionMode()) {
…
}
m_tree.openElements()->popAll();
…
void HTMLTreeBuilder::processEndOfFile(AtomicHTMLToken* token)
3. 소스분석 – <Head> tag / <Title> tag 처리
const size_t size = m_attachmentQueue.size();
…
AttachmentQueue queue;
for (size_t i = 0; i < size; ++i)
{
executeTask(queue[i])
}
if (task.nextChild)
task.parent->parserInsertBefore(task.child.get(), task.nextChild.get());
Else
task.parent->parserAppendChild(task.child.get());
…
}
void HTMLConstructionSite::executeQueuedTasks()
HTML
HEAD
TITLE
text
BODY
P
text
#4: DOM(Document Object Model)은 HTML 문서의 모든 요소에 접근하는 방법을 정의한 API다.
DOM 객체는 텍스트와 이미지, 하이퍼링크, 폼 엘리먼트 등의 각 문서 엘리먼트를 나타낸다. 자바스크립트 코드에서는 동적인 HTML을 만들어내기 위해 DOM 객체에 접근해서 조작할 수 있다
#7: Synchronous Mode(동기방식)
Allow Yield(양보 허용)
Force Synchronous (강제 동기)
#13: Vector<Attribute, 10> AttributeList;
Vector<UChar, 256> DataVector;
Attribute – in a class – in a class Rage(start, end), Range nameRange, Range valueRange, Vector<UChar, 32> name, Vector<UChar, 32> value;