기본 콘텐츠로 건너뛰기

[AngleSharp] 오픈 도큐먼트 워드 (ODT) xml 분해

    목차

참조

https://github.com/AngleSharp/AngleSharp/blob/master/doc/Basics.md

AngleSharp doc 자체 예시가 부족한 것인가... 아니면 내가 난독이 있는 것인가...

 

작성한 AngleSharp version : 0.12.1

 

 

오픈 도큐먼트 워드 프로세서 (ODT)서 아무 글귀나 작성한 다.

(오픈오피스는 https://www.openoffice.org/ 여기서 다운 받으면 된다, 또는 다른 툴에서 작업해서 odt로 저장하든가)

 

OpenOffice Wirter를 이용하여 아무 글귀를 적고 저장한다

오픈 도큐먼트 워드 프로세서 (ODT)는 압축파일로 취급하여 압축을 해제하면, 내부에 content.xml 이라는 파일이 있다. 해당 파일을 열만 다음과 같은 xml 구조로 구성되어 있음. (물론 일부 문서의 경우는 다를수 있으며, 가독성을 위해 개행을 했다.)

 

Xml 코드 예시 (접은글)

<?xml version="1.0" encoding="UTF-8"?>
<office:document-content 
	xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" 
	xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" 
	xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" 
	xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" 
	xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" 
	xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" 
	xmlns:xlink="http://www.w3.org/1999/xlink" 
	xmlns:dc="http://purl.org/dc/elements/1.1/" 
	xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" 
	xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" 
	xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" 
	xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" 
	xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" 
	xmlns:math="http://www.w3.org/1998/Math/MathML" 
	xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" 
	xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" 
	xmlns:ooo="http://openoffice.org/2004/office" 
	xmlns:ooow="http://openoffice.org/2004/writer" 
	xmlns:oooc="http://openoffice.org/2004/calc" 
	xmlns:dom="http://www.w3.org/2001/xml-events" 
	xmlns:xforms="http://www.w3.org/2002/xforms" 
	xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
	xmlns:rpt="http://openoffice.org/2005/report" 
	xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" 
	xmlns:xhtml="http://www.w3.org/1999/xhtml" 
	xmlns:grddl="http://www.w3.org/2003/g/data-view#" 
	xmlns:tableooo="http://openoffice.org/2009/table" 
	xmlns:textooo="http://openoffice.org/2013/office" 
	xmlns:field="urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0" 
	office:version="1.2">
	<office:scripts/>
	<office:font-face-decls>
		<style:font-face 
			style:name="Lucida Sans1" 
			svg:font-family="&apos;Lucida Sans&apos;" 
			style:font-family-generic="swiss"/>
		<style:font-face 
			style:name="바탕" 
			svg:font-family="바탕" 
			style:font-family-generic="roman" 
			style:font-pitch="variable"/>
		<style:font-face 
			style:name="Arial" 
			svg:font-family="Arial" 
			style:font-family-generic="swiss" 
			style:font-pitch="variable"/>
		<style:font-face 
			style:name="Lucida Sans" 
			svg:font-family="&apos;Lucida Sans&apos;" 
			style:font-family-generic="system" 
			style:font-pitch="variable"/>
		<style:font-face 
			style:name="바탕1" 
			svg:font-family="바탕" 
			style:font-family-generic="system" 
			style:font-pitch="variable"/>
	</office:font-face-decls>
	<office:automatic-styles>
		<style:style style:name="P1" style:family="paragraph" style:parent-style-name="Standard">
			<style:text-properties style:language-asian="ko" style:country-asian="KR"/>
		</style:style>
	</office:automatic-styles>
	<office:body>
		<office:text>
			<text:sequence-decls>
				<text:sequence-decl text:display-outline-level="0" text:name="Illustration"/>
				<text:sequence-decl text:display-outline-level="0" text:name="Table"/>
				<text:sequence-decl text:display-outline-level="0" text:name="Text"/>
				<text:sequence-decl text:display-outline-level="0" text:name="Drawing"/>
			</text:sequence-decls>
			<text:p text:style-name="P1">아무 문서나 입력 해보도록 하자....</text:p>
		</office:text>
	</office:body>
</office:document-content>

이 녀석은 MS word에서 Odt를 변환한 것을 읽은 것이다

 

 

 

이 녀석을 파싱하기 위해서 AngleSharp을 사용함.

NuGet 패키지에서 AngleSharp, AngleSharp.Io, AngleSharp.Xml을 설치한다.

(다른 라이브러리도 같이 설치 될 수 있다.)

 

using System;
using AngleSharp;
using AngleSharp.Html.Parser;

class MyClass {
    static async void Main() {
        //Use the default configuration for AngleSharp
        var config = Configuration.Default;

        //Create a new context for evaluating webpages with the given config
        var context = BrowsingContext.New(config);

        //Source to be parsed
        var source = "<h1>Some example source</h1><p>This is a paragraph element";

        //Create a virtual request to specify the document to load (here from our fixed string)
        var document = await context.OpenAsync(req => req.Content(source));

        //Do something with document like the following
        Console.WriteLine("Serializing the (original) document:");
        Console.WriteLine(document.DocumentElement.OuterHtml);

        var p = document.CreateElement("p");
        p.TextContent = "This is another paragraph.";

        Console.WriteLine("Inserting another element in the body ...");
        document.Body.AppendChild(p);

        Console.WriteLine("Serializing the document again:");
        Console.WriteLine(document.DocumentElement.OuterHtml);
    }
}

AngleSharp doc에서 제공하는 초기 사용방법이다.

  1. Configuration 선언
  2. BrowsingContext 생성
  3. OpenAsync로 Document 생성

의 순서를 따른다. 비동기 함수를 사용하는 점 유의해야 한다.

 

 

물론 Parser를 선언해서 초기화하는 방법도 있다.

var context = BrowsingContext.New(config);
var parser = context.GetService<IHtmlParser>();
var source = "<h1>Some example source</h1><p>This is a paragraph element";
var document = parser.ParseDocument(source);

 

 

본인은 아래와 같은 방법을 사용했다.

var config = Configuration.Default.WithXml();

string originalXmlString = System.IO.File.ReadAllText("xml 파일의 경로");

XmlParser parser = new XmlParser();

using (IXmlDocument odtDocument = parser.ParseDocument(originalXmlString))
{
	//여기서 아무 작업이나 진행
}

 

 

<office:document-content office:version="1.2" 
	xmlns:xlink="http://www.w3.org/1999/xlink" 
	xmlns:xhtml="http://www.w3.org/1999/xhtml" 
	xmlns:xforms="http://www.w3.org/2002/xforms" 
	xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" 
	xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" 
	xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" 
	xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" 
	xmlns:smil="urn:oasis:names:tc:opendocument:xmlns:smil-compatible:1.0" 
	xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" 
	xmlns:presentation="urn:oasis:names:tc:opendocument:xmlns:presentation:1.0" 
	xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" 
	xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" 
	xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" 
	xmlns:math="http://www.w3.org/1998/Math/MathML" 
	xmlns:grddl="http://www.w3.org/2003/g/data-view#" 
	xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" 
	xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0"
	xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0"
	xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:db="urn:oasis:names:tc:opendocument:xmlns:database:1.0"
	xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0"
	xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" 
	xmlns:anim="urn:oasis:names:tc:opendocument:xmlns:animation:1.0">
	<office:font-face-decls>
		<!-- 스타일 -->
	</office:font-face-decls>
	<office:automatic-styles>
		<!-- 스타일 -->
	</office:automatic-styles>
	<office:body>
		<office:text text:use-soft-page-breaks="true">
			<!-- 본문 -->
		</office:text>
	</office:body>
</office:document-content>

 

 

 

IXmlDocumnet (IDocument)는 루트라고 생각하면 된다.

IXmlDocument의 자식 Element 또는 Node부터 TagName이 <office:document-content> 로 시작한다.

※ 자식 요소를 구할 때, Children 또는 ChildNodes를 이용하여 구할 수 있다.

  • Children의 경우에는 Element collection으로 리턴
  • ChildNodes의 경우 Node list로 리턴

Node가 Element의 상위 클래스이기 때문에 Element에서 검출되지 않는 녀석들 (예 : TextNode)을 가져오려면, ChildNodes를 이용하는 것이 좋다.

 

office:document-content 노드의 객체 구조

요소 이름   설명
NamespaceUri urn:oasis:names:tc:opendocument:xmlns:office:1.0

prefix가 의미하는 네임스페이스

(여기서는 xmlns:office를 의미한다.)

NodeName office:document-content Prefix + LocalName
Prefix office 노드 이름에서 왼쪽, 네임스페이스 부분
LocalName document-content 노드 이름에서 오른쪽 부분
Attributes   현재 노드의 속성들
NodeType Element 현재 노드의 객체 타입 (예 Text, Element 등)
NodeValue null 노드 텍스트 값 (?)
TagName office:document-content NodeName과 유사해 보임
TextContent 아무 문서나 입력 해보도록 하자.... 텍스트 값만 출력
InnerHtml   현재 노드를 제외한 내부 Html을 출력
OuterHtml   InnerHtml에서 현재 노드도 포함

 

대략 이런 구조로 DOM이 구성되어 있다.


댓글