http://applejara.tistory.com/entry/%EC%97%90%EB%9F%ACThe-processing-instruction-target-matching-xXmMlL-is-not-allowed

위 링크의 내용을 참고했습니다.
아래는 자료 보존용입니다.


심각: Parse Fatal Error at line 10 column 6: The processing instruction target m
atching "[xX][mM][lL]" is not allowed.

org.xml.sax.SAXParseException: The processing instruction target matching "[xX][
mM][lL]" is not allowed.


이런 에러를 발생했습니다.
이것은  아래처럼 xml을 선언해 주실때


1. 공백(whitespace) 있거나

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

2. 주석이 있거나

<!-- xml 시작 -->
<?xml version='1.0' encoding='utf-8'?> 
하면 생기는 오류입니다.


xml의 선언부는 항상 문서의 제일 먼저 와야 합니다.

참고: http://www.yunsobi.com/tt/subby/99
참고: http://decoder.tistory.com/37

첨부된 파일은 검색에서 나온 것으로 문제 있으면 삭제하겠습니다.

package com.omp.bp.cms.batchreg.service;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

import org.apache.log4j.Logger;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.output.XMLOutputter;

import com.omp.bp.cms.batchreg.BatchRegisterErrorConstants;
import com.omp.bp.cms.util.DateUtil;

/**
 * 배치 등록 관련 에러 로그 처리 클래스. 콘텐츠 하나에 대한 에러로그XML 생성.
 * @author Sung,HongJe
 *
 */
public class BatchRegisterError {

    private final static Logger log = Logger.getLogger(BatchRegisterError.class);

    private final String ERROR_FILE_NAME_HEADER = "ERROR_";
    private final String ERROR_FILE_EXT = "XML";

    /**
     * 에러 로그 파일 생성
     * @param ftpRepoPath ftp 디렉토리 패스
     * @param contentId 콘텐츠ID
     * @param contentType 콘텐츠타입 - C:채널, E:콘텐츠(에피소드)
     * @param errorCode 에러코드
     * @throws IOException
     */
    public void makeErrorLog(String ftpRepoPath, String contentId, String contentType, int errorCode) throws IOException {

        // 1. ERROR 파일패스 설정 : ftpRepo/ERROR_[TYPE]_[CID].XML
        // 2. 에러 코드를 이용해서 XML 내용 설정
        // 3. 파일로 저장

        // ftpRepo/ERROR_C_000050151.XML
        String filePath = ftpRepoPath + File.separator + ERROR_FILE_NAME_HEADER + contentType.toUpperCase() + "_" + contentId + "." + ERROR_FILE_EXT;
        String errorMsg = BatchRegisterErrorConstants.getErrorMsg(errorCode);

        // XML 내용 생성
        Document xmlDoc = makeErrorXML(contentId, errorCode, errorMsg, DateUtil.getToday() + DateUtil.getTime());

        File file = new File(filePath);
        FileOutputStream out = null;

        try {

            if(!file.exists()) { // 로그 파일 없으면 생성

                File dir = new File(ftpRepoPath); // ftp 디렉토리가 없으면 생성
                if(!dir.exists())
                    dir.mkdir();

                file.createNewFile();
            }

            out = new FileOutputStream(file);
            XMLOutputter serializer = new XMLOutputter();
            serializer.output(xmlDoc, out);
            out.flush();
        }
        catch (IOException e) {

            log.error("BatchRegisterError.makeErrorLog 로그 파일 작성 중 예외 발생", e);
            throw e;
        }
        finally {

            if(out != null) {

                try {

                    out.close();
                }
                catch (IOException e) {

                    log.error("BatchRegisterError.makeErrorLog 로그 파일 작성 종료 중 예외 발생", e);
                }
            }
        }
    }

    /**
     * 에러 메시지를 담는 XML을 생성 후 반환
     * @param contentId
     * @param errorCode
     * @param errorMsg
     * @param dateTime
     * @return
     */
    private Document makeErrorXML(String contentId, int errorCode, String errorMsg, String dateTime) {

        Document doc = new Document();

        Element error_log = new Element("error_log"); // root

        Element content_id = new Element("content_id");
        content_id.setAttribute("id", contentId); // set CID

        Element msg = new Element("msg");
        msg.setText(errorMsg);

        Element code = new Element("code");
        code.setText(String.valueOf(errorCode));

        Element time = new Element("time");
        time.setText(DateUtil.getToday() + DateUtil.getTime());

        content_id.addContent(msg);
        content_id.addContent(code);
        content_id.addContent(time);

        error_log.addContent(content_id);

        doc.addContent(error_log);

        return doc;
    }
}


볼드체를 참고하기

참고: http://www.psuedoguru.com/roller/page/psuedoblog?entry=failed_to_create_an_xpathfactory

XPathFactory factory = XPathFactory.newInstance();
여기에서 아래와 같은 에러가 나올 때가 있다.

java.lang.RuntimeException: XPathFactory#newInstance() failed to create an XPathFactory for the default object model: http://java.sun.com/jaxp/xpath/dom with the XPathFactoryConfigurationException: javax.xml.xpath.XPathFactoryConfigurationException: No XPathFctory implementation found for the object model: http://java.sun.com/jaxp/xpath/dom

문제는 아래.

Finally found out that the problem was due to the Tomcat Java 1.4 compatibility libraries. I had recently upgraded to Java 1.5, but forgot to remove them.
$TOMCAT_HOME/common/endorsed/xercesImpl.jar
$TOMCAT_HOME/common/endorsed/xml-apis.jar

톰캣의 xml관련 api에서 문제가 밸생한 것임.
파일을 옮기던가 지우던가 하면 해결된다.
12장 동적 유효성 검사 프로그래밍도 패스.

13장 XPath 검색 프로그래밍


10장 SAX 기반 문서 처리 프로그래밍

빠르게 순차적으로 처리하기엔 좋으나, 한번 XML을 파싱한 다음 여러번 검색하기엔 안좋다.
순차적으로 검색하므로, 검색때마다 파싱해야함.


11장 XSLT 문서 변환 프로그래밍은 패스.
필요할 때 찾아볼 것
8장 XSL는 읽고 넘겼음. 필요할 때 찾아보면 될 듯.

9장 DOM 기반 문서 처리 프로그래밍

<parent>
  <element>TEXT</element>
</parent>

위의 경우 TEXT 자체도 노드로 취급한다는 점에 주의.
parent <- element <- TEXT 이런 식으로 상위 노드에 종속되어 있다.


<parent attr="ATTR">TEXT1
  <element>TEXT2</element>
</parent>

예를 들다보니 위와 같이 되었지만, 위와 같은 것은 없는듯.
TEXT1과 element의 레벨이 같아지므로, 관리불가!? 어느게 TEXT이고 어느게 element인지 알 수 없다. 전부 NODE이므로..
책이나 웹 찾아봐도 MIXED라는 것이, 문자 데이터 또는! 자식 엘리먼트이지, 문자 데이터와 자식 엘리먼트는 아니었음.


<parent attr="ATTR">
  <element>TEXT2</element>
</parent>

위의 경우도 마찬가지로  TEXT2, ATTR은 전부 하나의 노드로 취급한다. 하지만 속성은 그 값을 얻는 방식이 다르다.
parent <- element <- TEXT2
  <- ATTR

parent에 ATTR, element가 종속되어 있으나, ATTR 과 element는 동일 레벨이 아니다.
속성값(ATTR)을 얻을 때는 parent.getAttribute("attr");
TEXT1을 얻을 때는 eText = element.getFirstChild() 한 후, eText.getData();
1~5장까지는 훑어보면 알만한 내용.
6장 XML 스키마 언어는 조금 보다가 복잡해지고, 이번 프로젝트랑은 크게 상관없을 듯 하여 pass.
나중에 필요하면 찾아보는 걸로 해도 괜찮을 듯.

7장 XPath와 그 뒤의 DOM 기반 문서 처리, SAX 기반 문서 처리 쪽은 중요!

XPath관련

/child::booklist/child::book
루트 노드의 자식 노드인 booklist의 자식 노드인 book을 찾아라

/child::booklist/child::book/attribute::kind
루트 노드의 자식 노드인 booklist의 자식 노드인 book의 속성 kind값을 찾아라

/child::booklist/child::book[attribute::kind="computer"]
루트 노드의 자식 노드인 booklist의 자식 노드인 book 중에서, 속성 kind 값이 "computer"인 book 노드를 찾아라

/child::booklist/child::book[contains(child::title, "전자")]
루트 노드의 자식 노드인 booklist의 자식 노드인 book 중에서, book의 자식인 title 노드의 문자 데이터 값 중에 "전자" 가 포함된 book 노드를 찾아라.
<book>
    <title>전자사전</title>
</book>
뭐 이런거...

//book
XML문서 전체에서 book 노드를 찾아라.    /booklist/book 은 booklist의 자식 노드인 book을 찾는 것이므로 다르다.

/booklist/book[@kind="computer"]
루트 노드의 자식 노드인 booklist의 자식 노드인 book 중에서, book의 속성 kind의 값이 computer인 book 노드를 찾아라

//book[@kind="computer"]
XML문서 전체에서 속성 kind의 값이 computer인 book 노드를 찾아라

/booklist/book/title[../@kind="computer"]
루트 노드의 자식 노드인 booklist의 자식 노드인 book의 자식 노드인 title 중에서, title의 부모인 book 노드의 속성 kind 값이 computer인 title 노드를 찾아라


XPath 함수 사용

/booklist/book[position()=last()] 또는 /booklist/book[last()]
루트 노드의 자식 노드인 booklist의 자식 노드인 book 중에서, 마지막 위치에 있는 book 노드를 찾아라

/booklist/book[position()=2] 또는 /booklist/book[2]
루트 노드의 자식 노드인 booklist의 자식 노드인 book 중에서, 두번째 위치에 있는 book 노드를 찾아라

count(/booklist/book)
booklist 밑의 book 노드의 총 개수를 얻는다

/booklist/book[starts-with(title, '사')]
booklist 밑의 book 노드 밑의 title 노드의 컨텐츠 내용이 '사'로 시작하는 book 노드를 찾아라

/booklist/book[contains(title, 'XML')]
book 노드 중에서 자식 노드인 title 노드의 컨텐츠 내용에 'XML'이 포함되어 있는 book 노드를 찾아라

/booklist/book[not(contains(title, 'XML'))]
book 노드 중에서 자식 노드인 title 노드의 컨텐츠 내용에 'XML'이 포함되어 있지 않은 book 노드를 찾아라