제목:

자바스크립트로 XML 파싱하기 (jQuery)

날짜: Posted on

이전의 자바스크립트로 XML 파싱하기에서는 제이쿼리(jQuery)를 사용하지 않고 순수 자바스크립트로만 AJAX를 사용하였습니다. 하지만 제이쿼리를 이용하면 코드를 더욱 간결하게 만들 수 있습니다.

제이쿼리를 사용하여 이전 포스트의 자바스크트 부분의 코드를 다시 작성할 경우, 다음과 같이 됩니다.

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
		<script type="text/javascript">
			$(document).ready(function(){
				$.ajax({
					type: "GET",
					url: "xml_sample.xml",
					dataType: "xml",
					success: function (xml) {
						// Parse the xml file and get data
						$(xml).find("girlgroup").each(function(){
							$("#gname").html($(this).find("name").text());
							$(this).find("member").each(function(i){
								if (i != 0) { $("#members").append(", "); }
								$("#members").append($(this).text());
							});
							$(this).find("album").each(function(){
								$("#albums").append("<li>" + $(this).attr("order") +
									": " + $(this).text() + "</li>\n");
							});
						});
					}
				});
			});
		</script>
		<title>AJAX Sample with jQuery</title>
	</head>

	<body>
		<h2 id="gname"></h2>
		<p>멤버 구성: <span id="members"></span></p>
		<h3>앨범 목록</h3>
		<ul id="albums"></ul>
	</body>
</html>

이와 같이 길었던 자바스크립트 부분의 길이가 2/3 정도로 줄었습니다.

이 코드는 문서의 로드가 완료되면 AJAX 처리를 시작합니다. GET 방식으로 xml_sample.xml 파일의 데이터를 전송받는 데 성공하면 수행할 코드가 12번 줄과 25번 줄 사이에 묶여 있습니다. 14번 줄에서는 최상위 요소인 girlgroup을 찾아내서, 15번 줄에서는 girlgroup의 하위 요소인 name의 데이터값을 ID가 gname인 HTML 문서의 요소 안으로 넣습니다. 16번 줄부터 19번 줄까지는 member 요소의 수만큼 반복해서 각 member 요소의 데이터값을 ID가 members인 요소 안에 차례로 추가합니다. 20번 줄부터 23번 줄까지는 album 요소의 수만큼 반복해서 각 album 요소의 order 속성값과 데이터값을 ID가 albums인 ul 요소 안에 차례대로 li 요소로 추가합니다.

이 코드의 결과는 이전 포스트에서 예로 들었던 것과 같습니다.

9개의 댓글이 있습니다.

  1. 안녕하세요? 제가 관리하는 사이트에서 javascript로 xml을 파싱할 일이 생겼는데, 프로그램을 조금밖에 모르는 저로서는 이 포스트가 정말 큰 도움이 되고 있습니다. 정말 감사합니다. 제가 가진 파일로 테스트하였고 자꾸 문제가 생겨서 살펴보니, xml을 url로 제공받고 있는데 그 제공하는 곳에서 xml 파일
    첫줄이 빈줄이고 2번째줄부터 작성되는 바람에 xml이 유효하지 않은 문제가 생겼더군요. 그 업체에 빈 첫줄을 없애줄 것을 요청하였으나, 안된다고 하네요. 첫줄을 없애는 방법을 이래저래 검색해서 시도해보았는데, 전혀 되지 않아 끙끙대고 있습니다. 혹시 가능하시다면 도움주실 수 있으신지요? 위의 예제에서 무엇을 추가해야할지 전혀 모르겠습니다.ㅜㅜ

    1. 안녕하세요. 댓글 남겨 주셔서 감사합니다.

      XML 파일 첫 줄이 비어 있고 두 번째 줄부터 <?xml version="1.0" encoding="UTF-8"?> 이렇게 시작한다는 말씀이신가요? 이런 경우는 XML DTD가 반드시 첫 줄에 선언되어야 한다는 규칙을 위반하므로 잘못된 XML입니다.
      하지만 모종의 꼼수(?)를 쓴다면 이런 경우에도 파싱이 가능합니다.

      $(document).ready(function(){
      	$.ajax({
      		type: "GET",
      		url: "첫 줄이 빈 XML의 URL",
      		dataType: "text",
      		success: function (xxml) {
      			xml = $.parseXML( xxml.trim() ),
      			// Parse the xml file and get data
      			$(xml).find("최상위요소 이름").each(function(){
      				// 코드가 들어갈 곳
      			});
      		}
      	});
      });
      

      이런 식으로 jQuery 스크립트를 짜면 됩니다. 5번 줄에서 dataType이 xml이 아닌 text로 되어 있는 것을 볼 수 있는데요. 이는 일단 첫 줄이 비어있는 잘못된 XML 문서를 일반 텍스트로 취급해서 읽는 것입니다.

      그리고 성공하면, 7번 줄에서 parseXML() 메소드를 써서 일반 텍스트 형태로 받아들인 XML 문서를 XML 형식으로 바꿔야 하는데, 중요한 것은 여기서 XML 문서를 문자열 형태로 받아들인 변수에다가 trim() 메소드를 써서 인자로 넣는다는 것입니다. trim() 메소드는 문자열 양 끝의 공백을 제거하는 기능을 합니다. 이렇게 되면 첫 줄의 공백이 제거되면서 두 번째 줄에 있던 DTD가 첫 줄로 옮겨가게 되고 올바른 XML이 되어 파싱이 가능해집니다. 그리고 그 이후는 본문에 설명한 것과 같습니다.

      많은 도움 되셨기를 바랍니다.

      1. 자세하고 빠른 답변 정말 감사드립니다.^^
        말씀해 주신대로, 한줄 공백을 강제로 만들어 test.xml 파일을 만들고 테스트해 본 결과 대성공이네요, 대박!!
        그런데, 실제 url을 넣으면 아무 정보도 뜨질 않아요.
        krx 사이트에서 주가 정보 등을 가져오려고 하는데, 예를 들어 다음과
        같은 URL 입니다. http://asp1.krx.co.kr/servlet/krx.asp.XMLSise?code=035420
        잘은 모르지만 구글링을 해보았는데요, 혹시 이게 크로스 도메인 문제인가요?
        제 사이트와 xml을 가져오는 사이트가 다르면 이런 문제가 생기는건지요?
        이런 경우에는 어떤 방법이 있을까요?
        바쁘실텐데, 자꾸 귀찮게 해드려서 죄송합니다.

        1. 안녕하세요. 댓글 남겨 주셔서 감사합니다.

          실험할 때는 잘 되었지만 막상 실제로 적용해 보면 아무것도 안 뜬다는 말씀이시지요?
          구글 크롬에서 F12 키를 눌러서 검사를 해 본 결과 “No ‘Access-Control-Allow-Origin’ header is present on the requested resource. Origin ‘(URL 주소)’ is therefore not allowed access.” 오류가 발생하는 것을 확인하였습니다. 이 경우는 서버 측에서 외부 접근을 막아 놓은 경우이기 때문에 자바스크립트로는 방법이 없습니다.

          그러나 우회적인 방법으로 해결이 가능한데, PHP가 지원된다고 하셨으니 PHP의 CURL 라이브러리를 활용하면 가능합니다.

          <?php 
          	$ch = curl_init(); 
          	
          	curl_setopt($ch, CURLOPT_URL, "http://asp1.krx.co.kr/servlet/krx.asp.XMLSise?code=035420");
          	curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
          	$output = trim( curl_exec($ch) );
          	
          	header('Content-Type: text/xml');
          	echo $output;
          	
          	curl_close($ch);
          ?>
          

          프로그램 전체를 통째로 PHP로 짜는 게 어렵다면 위와 같이 CURL 라이브러리를 이용하여 대상 사이트의 내용을 전사하는 PHP 프로그램을 만들어 웹 서버에 올리고 그 PHP 프로그램이 구동되는 URL로 AJAX를 돌리는 방법을 쓸 수도 있습니다. 이 PHP 프로그램을 예를 들어 ‘xml_sise.php’라고 저장했다면 jQuery의 AJAX URL도 ‘xml_sise.php’ 이렇게 하면 되겠습니다. 그리고 여기서는 PHP의 CURL로 대상 사이트의 내용을 전사하는 과정에서 미리 첫 줄을 없애기 때문에 굳이 일반 텍스트로 불러와서 XML로 변환하는 과정 없이 곧장 XML로 불러오는 방법을 써도 잘 돌아갑니다.

          많은 도움 되셨기를 바랍니다.

          1. 위 php코드를 사용해서 xml을 받아와서 가공을 하려고 합니다.
            그런데 http://asp1.krx.co.kr/servlet/krx.asp.XMLSise?code=003570 주소를 입력하면
            에러가 납니다. 그 이유를 모르겠습니다.
            아래주소는 정상으로 파싱이 됩니다.
            도와주세용.ㅜㅜ

            TBL_StockInfo->attributes()->JongName;

            curl_close($ch);
            ?>

          2. 코드를 보니 자바스크립트가 아닌 PHP에서 직접 파싱을 하는 것으로 보이네요. 아래는 참고 포스트입니다.
            https://pjw48.net/wordpress/2017/02/16/xml-parsing-php/
            PHP로 XML 파싱하기 포스트입니다.

            XML이 에러가 나는 이유를 분석해 보니 & 표시가 HTML 엔티티로 적혀 있지 않고 단독으로 적혀 있음이 확인되었습니다.
            HTML과는 달리 XML은 문법이 엄격해서 & 표시도 &amp; 식으로 HTML 엔티티로 작성해야 합니다.

            아래와 같이 PHP로 코딩해서 파싱 테스를 해 본 결과 정상적으로 작동합니다.

            <?php 
                $ch = curl_init(); 
                 
                curl_setopt($ch, CURLOPT_URL, "http://asp1.krx.co.kr/servlet/krx.asp.XMLSise?code=003570");
                curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
                $output = trim( curl_exec($ch) );
                
                // 홀로 쓰인 & 표시를 &amp; 엔티티로 변경
                $output = preg_replace('/&(?![#0-9A-Za-z]+;)/', '&amp;', $output);
                
                $xml=simplexml_load_string($output);
                
                header('Content-Type: text/html; charset=utf-8');
                
                echo $xml->TBL_StockInfo->attributes()->JongName;
                // 위 코드는 $xml->TBL_StockInfo['JongName']으로 써도 됩니다.
                 
                curl_close($ch);
            ?>
            
      1. &에 문제가 있을거 같았는데. 해법을 몰라서 고생했는데.
        가르쳐주셔서 감사드립니다.^^

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다