반응형

출처: 

XML 원리와 응용, 홍성용, 한빛미디어
http://www.w3schools.com/dom/dom_nodes_navigate.asp

http://forums.asp.net/t/1227814.aspx?xml+SelectNodes+not+working+in+firefox+in+javascript+

http://help.dottoro.com/ljcovvhi.php

http://help.dottoro.com/ljruhkuj.php

http://forums.mozillazine.org/viewtopic.php?f=19&t=605133&start=0






	
		HyeRi
		22
		Korean
	

 
var objDOM;
	var browser = navigator.userAgent.toLocaleLowerCase();
	
	if (browser.indexOf('firefox') != -1) {
		objDOM = document.implementation.createDocument("", "", null);
		objDOM.async = false;
		objDOM.load("ex.xml");
	} else if (browser.indexOf('trident') != -1) {
		objDOM = new ActiveXObject("MSXML.DOMDocument");
		objDOM.async = false;
		objDOM.load("ex.xml");
	} else {
		// Chrome, Safari, Opera
		xhttp = new XMLHttpRequest();
		xhttp.open("GET", "ex.xml", false); // https://xhr.spec.whatwg.org/#the-open%28%29-method
		xhttp.send();
		objDOM = xhttp.responseXML;
	}
	
	
	function getNodeName() {
		var objNode;
		objNode = objDOM.documentElement.firstChild;
		while (objNode.nodeType != 1)
			objNode = objNode.nextSibling;
		alert(objNode.nodeName);
	}
	
	function getNodeValue() {
		var objNode;
		objNode = objDOM.documentElement.firstChild;
		while (objNode.nodeType != 1)
			objNode = objNode.nextSibling;
		alert(objNode.nodeValue);
	}
	
	// Confirm the document's structure
	function documentStructure() {
		if (browser.indexOf('trident') != -1) {
			alert(objDOM.xml)
		} else {
			var serializer = new XMLSerializer();
			alert(serializer.serializeToString(objDOM));
		}
	}
	
	// Copy the document's first node
	function nodeCopy() {
		var objNode;
		objNode = objDOM.documentElement.firstChild;
		while (objNode.nodeType != 1)
			objNode = objNode.nextSibling;
		
		var newNode;
		newNode = objNode.cloneNode(false);
		objNode.appendChild(newNode);

		if (browser.indexOf('trident') != -1) {
			alert(objDOM.xml);
		} else {
			var serializer = new XMLSerializer();
			alert(serializer.serializeToString(objDOM));
		}
	}
	
	// Append the firstNode next to first attribute
	function appendNode() {
		var objNode;
		
		if (browser.indexOf('trident') != -1) {
			objNode = objDOM.selectSingleNode("/students/student");
		} else {
			
			function cus_selectSingleNode(xmlDoc, elementPath){   
				if (document.implementation && document.implementation.createDocument) {
					var nodes;
					nodes = xmlDoc.evaluate(elementPath, xmlDoc, null, XPathResult.ANY_TYPE, null);
					
					
					var results = nodes.iterateNext();
					return results;       
				}   
			}
			
			objNode = cus_selectSingleNode(objDOM, "/students/student");
		}
		
		while (objNode.nodeType != 1)
			objNode = objNode.nextSibling;
		
		var newNode;
		newNode = objNode.cloneNode(false);
		objNode.insertBefore(newNode, objNode.firstChild);

		if (browser.indexOf('trident') != -1) {
			alert(objDOM.xml);
		} else {
			var serializer = new XMLSerializer();
			alert(serializer.serializeToString(objDOM));
		}
	}
	
	// Replace the firstNode next to first attribute
	function replaceNode() {
		var objNode;
		objNode = objDOM.documentElement.firstChild;
		while (objNode.nodeType != 1)
			objNode = objNode.nextSibling;
		
		var newNode;
		var oldNode;
		var oldNode2;
		
		newNode = objNode.cloneNode(false);
		oldNode = objNode.childNodes;
		alert(oldNode);
		oldNode2 = oldNode[1];
		alert(oldNode2);
		objNode.insertBefore(newNode, objNode.firstChild);

		if (browser.indexOf('trident') != -1) {
			alert(objDOM.xml);
		} else {
			var serializer = new XMLSerializer();
			alert(serializer.serializeToString(objDOM));
		}
	}


역시나 브라우저 호환성은 밥말아먹은 예제 덕에 조금 고생 좀 했다.
내 책이 2012년에 나온 판인데, 어째서 IE만을 위한 예제만 있는지 모르겠다.

분명 나는 2004, 5년부터 IE는 결제용이 되었건만......


하여튼 어제 찾아낸 브라우저 검색 코드면 될 줄 알았는데, 막상 그건 또 아니였다.

그래서 달라진 것만 조금 얘기하고자 한다.


getNodeName()과 getNodeValue()는 각각 노드의 이름과 값을 가져오는 것이다.

그런데 보면 while 루프문이 설정되어 있는 것을 볼 수 있다.

노드 타입이 1일 때 반복문을 멈추고 함수가 계속된 동작을 하란 얘기인데,

이렇게 하지 않으면 익스플로러를 제외한 브라우저는 빈 공간도 노드로 인식하기 때문이다.

정확하게는 이 빈 공간을 노드 타입 3인 텍스트 노드로 인식한다.

물론 XML에서 처음부터 빈 공간을 안 쓰는게 가장 좋은 방법이지만,

자기가 만든 것이 아니라면 이럴 수도 있다는 건 알아두는 게 좋을 거 같다.


그리고 documentStructure() 함수는 가져온 XML을 자바스크립트 대화 상자로 뿌리는 함수이다.

그런데 문제는 xml 변수가 ActiveXObject에만 있는 것으로 보인다.

그래서 다른 함수에서는 XMLSerializer 객체를 이용하여 구현했다.

사실 IE에서도 XMLSerializer 객체는 지원한다.


https://msdn.microsoft.com/ko-kr/library/system.xml.serialization.xmlserializer%28v=vs.110%29.aspx


여기에도 나와있지만 버젓이 msdn에서 설명해주고 있다.

다만 대화상자로 출력하는 것이 안 되기 때문에 따로 구현해야 했다.


appendNode() 함수는 우리가 찾은 노드 뒤에 같은 노드를 삽입하는 함수이다.

그런데 selectSingleNode() 함수 역시 익스플로러 밖에 없었다.

그래서 구글링하여 사용자가 직접 selectSingleNode() 함수를 만들어야 한다고 했다.

내가 본 원형 함수에서는 document 객체에서 evaluate() 함수를 호출했으나(document.evaluate()) 

파이어폭스에서는 이렇게하면 다음 에러가 났다.

"Node cannot be used in a document other than the one in which it was created"

영어 사전까지 찾아본 결과 "노드는 그 노드를 만든 문서 외에 다른 곳에 쓸 수 없다"는 뜻으로 보인다.

여튼 그 말대로 노드를 만든 문서(위 함수에서는 xmlDoc)에서

XPath 정규식을 평가하고 XPathResult 객체를 만드는 evaluate() 함수를 호출하니까 되었다.

다른 브라우저도 저렇게 하니까 되었기에 따로 분기를 만들지 않았다.

조금 슬픈 사실은 저 evaluate() 함수는 익스플로러에서는 지원되지 않는다는 사실이다.


여튼 이렇게 해서 또 하나의 예제를 마칠 수 있었다.


안 그래도 예비군 갔다와서 짜증나는데 이런 거까지 발목을 잡으니 현역같은 느낌이다.

한 마디로 좆같다.


2015.05.18 추가 내용

다시 공부하다가 막히는 부분을 확인하는 과정에서 여기에 적지 않은 것이 있어서 다시 적는다.

replaceNode()에서 oldNode2 = oldNode[1]; 부분을

책에서는 대괄호 대신 소괄호, ()로 감싸고 있었다.

그러나 그렇게 하면 익스플로러만 되므로

나머지 브라우저에서도 사용하려면 대괄호, []로 묶어야 한다.


반응형
Posted by 애콜라이트
l

free counters