Well-formed XML DocumentWell-formed XML Document

Posted at 2009. 1. 23. 22:36 | Posted in 프로그래밍 언어/XML
> Well-formed XML

Well-formed XML이란 xml 문법을 지킨 xml 문서를 의미한다.
비슷한 것으로 Valid XML Document가 있다. 이는 Well-Formed XML이면서, 즉 XML 문서의 문법을 전부 지킨 문서이면서 DTD, XML Schema등으로 정의된 문서의 구조까지 지킨 문서이다.
만약 XML 문서를 지키지 않았다면(Well-Formed하지 않다면) XML Parser는 Fatal Error를 발생시키고 파싱을 중단한다. 그리고 만약 문법은 지켰으나 DTD, XML Schema등으로 정의된 문서의 구조를 지키지 않았다면 ERROR를 발생시킨다. 이 경우 Parser는 끝까지 문서를 파싱한다.

그러면 XML 문법 몇 가지를 이 XML 문서 예제를 기반으로 설명을 하겠다

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

<!-- XML MULTIPLE LINE COMMENTS -->
<bookstore>
    <book category="CHILDREN">
        <title>Harry Potter</title>
        <author>J K. Rowling</author>
        <year>2005</year>
        <price>29.99</price>
    </book>
    <book category="WEB">
        <title>Learning XML</title>
        <author>Erik T. Ray</author>
        <year>2003</year>
        <price>39.95</price>
    </book>
</bookstore>


> XML Declaration - XML 문서 정의

<?xml version="1.0" encoding="utf-8" standalone="[yes|no]"?>
현재 text파일이 XML 문서임을 나타내는 문장이다. 문서의 가장 처음에 작성해야 하는 문장으로 세 가지 속성을 순서대로 표기해야 한다.
version 속성은 반드시 들어가 있어야 하는데 이는 XML 문법이 ver.마다 달라서 XML Parser가 이 문서를 파싱할 때 참조해야 하기 때문이다.
standalone="yes"는 이 문서가 외부파일을 참조하지 않고 있다는 것을 의미한다.


> XML Element
    <book category="CHILDREN">
            <title>Harry Potter</title>
    </book>

Element(<book>)는 또 다른 element (<title>)나, Text(Harry Potter), attribute(category="CHILDREN")를 여러 개 가질 수 있다. element의 이름은 ID값이 아닌 단지 이름이기 때문에 중복이 되어도 상관 없다. 파일 타입이 utf-8일 경우 한글이름도 지원한다.(위의 xml encoding 말고 파일 저장 타입)
XML 문서는 최상위 element가 반드시 단 한 개 존재해야 한다. 그리고 시작태그(<title>)와 끝 태그(</title>의 이름이 일치해야 한다. 차이점은 끝 태그에는 element의 이름 앞에 /가 들어간다는 것 뿐이다. 또한 <A><B>text</A></B> 처럼 중첩된 구조는 가질 수 없다. Empty Element라는 것이 있다. 이는 Element가 element나 text를 가지지 않은 경우를 말한다.(속성은 가지고 있어도 되..나?) 이 경우 표현이 <empty></empty> 가 되겠고 줄여서 <empty/>로 표현한다.끝 태그와 다르게 /가 뒤에 붙어있음에 주의.


> XML Element - Naming

문자 숫자 _ . : - 가 사용 가능하다. 대소문자를 구별하므로 <upper>와 <Upper>는 다른 이름의 element이다. element의 이름에 공백이 들어가선 안 되고 첫 글자로 숫자 . - 가 와선 안 되며 xml이란 글자가 대소문자 형태 막론하고 와선 안 된다. :, -, .는 element 이름의 중간에 선언 가능하나 다른 연산자와 헷갈리므로 되도록 사용하지 않도록 해야 한다.


> XML Text - PCDATA, CDATA

PCDATA는 XML 파서가 parsing을 시도하는 데이터로 <element></element>로 둘러쌓인 Text contents라 생각하면 되겠다.

<element>PCDATA!!</element>

따라서 <& 는 PCDATA에 올 수 없다. 이는 XML 문서에서 사용되는 keyword이기 때문이다. 이와 같은 값을 표시하기 위해선 두 가지 방법이 있다.
1. < 는 &lt;, & 는 &amp;, > 는 &gt;
    >는 써도 파싱에러는 나지 않지만 < 가 &lt;밖에 안 되므로 통일성 있게 사용해 주면 좋다
    예: <element>(7 &lt; 8) &amp;&amp; (9 &lt; 10)</element>
2. <![CDATA[ contents ]]>
    xml parser가 파싱을 시도하지 않는다. 따라서 다음과 같이 쓸 수 있다.
    <element><![CDATA[ (7 < 8) && (9 < 10)]]></element>
    단, CDATA 구간 내에 ]]>가 오면 안 된다. <![CDATA[CDATA 구간]]> PCDATA 구간]]> 이 아니다. 그냥 parsing error 뜬다.


> XML Attribute

<book category="CHILDREN">

element에 대한 설명, metadata of metadata라 할 수 있다. 형태는 attr_name = "attr_value(쌍따움표)" 혹은 'attr_value(따움표)'을 사용하고 그 값으로 <&를 가질 수 없다. 속성은 element처럼 여러개가 가능하나 같은 이름의 속성을 가질 수 없다. <book category="children" category="IT"> 가 불가능하단 의미이다. 하지만 xml 문서는 대소문자를 구분하기 때문에 <book category="children" Category="IT"> 식으로 쓸 수는 있지만 좋지 않다.

속성에서 따움표 "를 표현하는 방법으로는 &quot;를 사용하거나 속성값을 작은따움표 ' 로 묶는 방법이 있다..
<book category=" &quot;WEB&quot; app. ">
<book category=' "WEB" app. '>
그러나 html에서 사용하던 방법인 <book category="\"WEB\" app.">는 허용되지 않는다.


> XML 주석

html에서 사용하던 주석과 같다.
<!-- 주석내용 -->
주석내용으론 < & 등 어떤 것도 올 수 있으나 -- 는 올 수 없다.


> Processing Instructions
<?PI_name PI_data?>
예를 들면 <?Query SELECT * FROM table_name?>로 app.에게 어떤 일을 하도록 명령하기 위한 용도. 많이 쓰이지는 않는다.
   

//

XML이 뭐임?XML이 뭐임?

Posted at 2009. 1. 23. 21:03 | Posted in 프로그래밍 언어/XML
XML은 Extensible Markup Language의 약자로 데이터를 저장하고 전송하는 데 목적을 갖고 있다.

<letter>
    <to>to name</to>
    <from>from name</from>
</letter>


HTML vs. XML

HTML하고 비슷한 모양이지만 HTML과 XML은 목적이 다르다. HTML데이터를 어떻게 보여줄 것인가에 중점을 두고 있다. HTML 태그들 마다 브라우저가 브라우징하는 모습이 다른 것을 보면 알 수 있다. 그에 반해 브라우저로 암만 여러 형태의 XML 문서를 열어 봤자 그 형태는 똑같다. 이는 XML은 문서에 기술된 데이터가 무엇인가에 중점을 두고 있기 때문이다.


특징

XML 문서에 쓰이는 태그들은 작성자가 직접 정의할 수 있다. 어떤 이름을 써도 상관 없지만 XML 문법에서 정의한 naming 규칙을 따라야 한다. 또한 XML문서는 TEXT 파일이다. Text 파일은 ASCII로 구성되어 HW, SW에 독립적이기 때문에 여러 app.에서 부담 없이 처리 가능하다. 즉 보편성이 특징이다. 이와는 다르게 Binary 파일은 파일의 구조 정의가 사용되는 app.마다 다르지만 해당 app.가 빠르게 이해할 수 있다는 효율성이 장점이다.

이와 같은 특징 때문에 다음과 같은 일이 가능하다
<letter>
    <to>to name</to>
    <from>from name</from>
</letter>

이 문서에
<letter>
    <date>2009/01/21</date>
    <to>to name</to>
    <from>from name</from>
</letter>

이럴 경우 binary 파일이라면 해당 파일이 사용되는 app.라 하더라도 구조가 달라졌기 때문에 파싱 과정에서 에러가 날 가능성이 매우 높다. 하지만 XML 문서는 text 파일이기 때문에 보편적인 XML Parser를 사용하더라도 에러가 발생하지 않는다.
//

[Java] 익명 클래스 (Anonymous Class)[Java] 익명 클래스 (Anonymous Class)

Posted at 2009. 1. 11. 17:39 | Posted in 프로그래밍 언어/Java
Form GUI 프로그래밍을 할 때 버튼 없이는 되는게 없다는 생각을 할 정도로 GUI 프로그래밍을 할 때 버튼은 거의 꼭 넣곤 한다. 예전에 Swing을 써서 어플리케이션을 만들었는데 버튼에 이벤트를 줘야 했다. 그러나 Swing은 처음. 익명 클래스? 그게 뭥믜 할 시절, 난 다음과 같이 코드를 싸질렀다.
class ButtonActionListener implements ActionListener
{
    public void actionPerformed(ActionEvent e)
    {
        // Do something...
    }
}

// in main..

JButton button = new JButton("OK");
button.addActionListener(new ButtonActionListener());

버튼 하나 만들 때마다 클래스 수가 증가했고 보기도 힘들더라... 고작 actionPerformed 메서드 하나 있는 ActionListener 인터페이스를 구현해서 넣을 건데 클래스를 따로 만들어야 되다니!!

찾아보니 자바엔 Anonymous Class가 있더라. 뭔고 하니 다음과 같은 것이다.

JButton button = new JButton("OK");
button.addActionListener ( new ActionListener() {
    public void actionPerformed(ActionEvent ev)
    {
        // Do Something...
    }
} );

클래스를 따로 만들 필요가 없다. new 구현한 클래스 이름() 대신, 그냥 위와 같이
new 구현하고자 하는 인터페이스 이름() {    구현해야 하는 메서드 구현    }
끝이다.

다른 표현으론 요론식

interface MyInterface
{
    public void function();
}
public class AnonymousClassFromInterface {
    public static void main(String[] args)
    {
        MyInterface mi = new MyInterface(){
            public void function(){
                System.out.println("익명함수");
            }
        };
        mi.function();
    }
}

output >> 익명함수

인터페이스를 구현한 객체를 만들어야 하는데 그 객체는 어떤 부분에서 제한적으로 사용이 되고 구현해야 하는 메서드 숫자도 매우 적을 경우 익명 클래스를 사용하면 좋다.

↑ 참고사이트: http://happystory.tistory.com/64

만약 Swing에서 한 패널이 있고 그 패널에 버튼이 있는 상태인 경우, 그 패널을 클래스화 시켜서 사용중이라면 다음과 같은 방법도 가능하다.

class SomePanel extends javax.swing.JPanel implements ActionListener{
    private
JButton button1;
    private JButton button2;
    private JButton button3;
    public SomePanel(){
        button1 = new JButton("버튼1");
        button1.addActionListener(this);
        this.add(button1);

        button2 = new JButton("버튼2");
        button2.addActionListener(this);
        this.add(button2);

        button3 = new JButton("버튼3");
        button3.addActionListener(this);
        this.add(button3);
    }
    public void actionPerformed(ActionEvent arg0) {
        // Do Something...
        Object obj = arg0.getSource();
        if(obj == button1) {
            System.out.println("버튼1");
        } else if(obj == button2) {
            System.out.println("버튼2");
        } else if(obj == button3) {
            System.out.println("버튼3");
        }
    }
}


옛날에 구현해 놓은거 열어 보니 저렇게 구현이 되어 있었다. 뭘 보고 저렇게 구현했는지는 잘 모르겠다-_-;; 그런데 리스너로 this 막 넘겨주고 해도 괜찮을까 모르겠다.  메모리 해제가 안 될 것 같기도 하고;;
참고로 getSource() 는 이벤트가 일어난 객체를 리턴한다. 패널의 모든 버튼이 같은 일을 하면 필요 없겠지만 보통 안 그렇기 때문에 저런 방법을...

//

[Ruby] 웹 소스 긁어오기[Ruby] 웹 소스 긁어오기

Posted at 2009. 1. 1. 16:35 | Posted in 프로그래밍 언어/Ruby
웹 소스..라기 보단 웹 요청에 대한 결과물 html 소스라고 해야할까.
PHP에서 하던 것처럼 소켓으로 웹 페이지를 요청하여 그 결과를 받아오는 식으로 코딩하였다.

class TinyWebBrowser
    require 'socket'
   
def initialize(host, port)
       
@host = host
        @port = port
        @socket = TCPSocket.new(host, port)
    end
    def print_page(path)
        request = "GET #{path} HTTP/1.0\r\n"
        request += "Host: #{@host}\r\n"
        request += "Connection: Close\r\n\r\n"
        @socket.write(request)
        response = @socket.read
        return response.split("\r\n\r\n", 2) # 헤더와 웹 소스 분리
   
end
    def close_browser
        @socket.close
    end
end

if __FILE__ == $0
    wb = TinyWebBrowser.new('berorev.pe.kr', 80)
    header, body = wb.print_page('/index.php')
   
File.open('out.txt', 'w') do |fp|
        fp.puts body
   
end
    wb.close_browser
end

HTTP/1.1로 전송해 봤더니 결과의시작과 끝에 17856과 0 이라는 숫자가 붙어 있었다.
1.0으로 보내 봤더니 깔끔하네;; 이유는 잘 모르겠다..'ㅡ';;

여튼 print_page를 호출한 결과로 html 소스를 얻어 보통 정규식 등의 작업을 진행할 것이다.


그런데.... 이미 라이브러리로 만들어진 게 있네.. 이런!!
require 'net/http'
html = Net::HTTP.get 'berorev.pe.kr', '/index.php'
File.open('out2.txt', 'w') do |fp|
     fp.puts html
end

//

[MFC] 폴더 생성 및 파일 생성[MFC] 폴더 생성 및 파일 생성

Posted at 2009. 1. 1. 02:59 | Posted in 프로그래밍 언어/C/C++/MFC
1. 폴더 생성

CreateDirectory(_T("main"), NULL);
CreateDirectory(_T("main/sub1"), NULL);

첫번째 인자는 만들 디렉토리 이름, 두 번째 인자는 security 설정인데 패스;
CreateDirectory 함수는 MFC로 프로젝트를 만들면 기본적으로 사용할 수 있는 함수이다.
main/sub 식으로 만들기 위해선 main 디렉토리를 만든 이후 main/sub 디렉토리를 만들어야 한다.

만약 아무 디렉토리도 없는 상태에서 main/sub/subsub 를 만들고자 한다면 다음과 같이 할 수 있다.
void CreateFolder(CString csPath)
{
    // UpdateData(TRUE);
    // csPath = m_csTopFolderName + csPath;

    CString csPrefix(_T("")), csToken(_T(""));
    int nStart = 0, nEnd;
    while( (nEnd = csPath.Find('/', nStart)) >= 0)
    {
        CString csToken = csPath.Mid(nStart, nEnd-nStart);
        CreateDirectory
(csPrefix + csToken, NULL);

        csPrefix += csToken;
        csPrefix += _T("/");
        nStart = nEnd+1;
    }
    csToken = csPath.Mid(nStart);
    CreateDirectory(csPrefix + csToken, NULL);
}

CreateFolder(_T("main/sub/subsub"));식으로 호출하면 된다.

while 문에서 / 단위로 끊어 읽으면서 디렉토리를 생성한다.
while 문 안에서 main, main/sub 디렉토리가 생성되며
while 문 밖에서 main/sub/subsub 디렉토리가 생성된다.

여기서 무작정 CreateDirectory를 호출하지 않고 csToken 값에 . 이 있는지를 검사한다.
. 이 포함되어 있다면 파일이므로 CreateDirectory가 아닌 CFile 등의 방법으로 파일을 만들도록 코드를 수정하면
CreateFolder(_T("main/sub/subsub.cpp"));식으로도 사용할 수 있을 것이다
아래 박스 코드를 위 코드의 CreateDirectory(...) 대신 쓰면 된다.

if(csToken.Find('.') >= 0)
    CreateFile(csToken, csPrefix);
else
    CreateDirectory(csPrefix + csToken, NULL);

물론, 폴더 이름에 . 을 넣거나 하면 낭패다-_-;

2. 파일 생성

파일이 존재하지 않으면 기본적인 내용을 추가하여 파일을 생성하고, 존재하면 건너뛰는 코드이다.

void CreateFile(CString csFileName, CString csPrefix)
{
    CFile file;
    if(!file.Open(csPrefix + csFileName, CFile::modeRead))
    {
        file.Open(csPrefix + csFileName, CFile::modeCreate|CFile::modeWrite);
        file.Write(~~~~);
    }
    file.Close();
}


사실, 파일이 존재하면 그 파일 내용을 지우지 않고 여는 방법은 단순하다.

CFile file(_T("main.cpp"), CFile::modeCreate|CFile::modeNoTruncate);

하지만 파일이 존재하면 아무 일도 하지 않고,
파일이 존재하지 않을 때 파일을 생성 및 기본적인 내용을 추가하려 한다면
modeNoTruncate 로 여는 것으론 해결할 수 없다.

예 >> a.cpp 파일을 생성하는데 파일이 없으면 int main(){ return 0; } 을 넣어 생성하고,  
    >> 파일이 있다면 아무 일도 수행하지 않으려 하는 경우.
    >> 기껏 a.cpp 코딩 다 해 놨는데 이 파일을 위와 같은 초기화 파일로 만들면 슬퍼지니까;;;


//