2013-02-02 4 views
5

사용자 입력을 클라이언트 측 (JavaScript)의 XML 문서에 저장하고이를 서버에 전달하여 지속성을 유지하려고합니다.XMLSerializer()를 사용하여 직렬화하기 전에 XML에서 유효하지 않은 문자 제거

예를 들어 한 명의 사용자가 STX 문자 (0x2)가 포함 된 텍스트에 붙여 넣습니다. XMLSerializer는 STX 문자를 이스케이프하지 않으므로 올바른 형식의 XML로 직렬화되지 않았습니다. 또는 .attr() 호출이 STX 문자를 이스케이프 했어야했는데 두 경우 모두 유효하지 않은 XML이 생성되었습니다.

난에 브라우저 XmlSerializer를() 항상 잘 형성되지 않은의 출력을 찾는거야 (심지어 브라우저의 자신의 DOMParser()를

이 예 만족하지 않고는 STX 문자는 것을 보여준다 제대로 XmlSerializer를()로 인코딩되지 :

> doc = $.parseXML('<?xml version="1.0" encoding="utf-8" ?>\n<elem></elem>'); 
    #document 
> $(doc).find("elem").attr("someattr", String.fromCharCode(0x2)); 
    [ <elem someattr=​"">​</elem>​ ] 
> serializedDoc = new XMLSerializer().serializeToString(doc); 
    "<?xml version="1.0" encoding="utf-8"?><elem someattr=""/></elem>" 
> $.parseXML(serializedDoc); 
    Error: Invalid XML: <?xml version="1.0" encoding="utf-8"?><elem someattr=""/></elem> 
가 항상 잘 형성됩니다 어떻게에서 브라우저 (임의의 사용자 입력에 의해 결정 PARAMS로) XML 문서를 생성해야하도록

(모든 것이 올바르게 이스케이프)? IE8 또는 IE7을 지원할 필요가 없습니다.

(예, 서버 쪽에서 XML의 유효성을 검사하지만 브라우저가 서버에 형식이 올바르지 않은 문서를 전달하는 경우 서버가 수행 할 수있는 최선의 방법은 불만입니다. 이는 빈약 한 사용자에게 도움이되지 않습니다. 사용자) 여기

+0

필요에 따라 엔티티로 변환하여 문자 단위로 소스 문자열을 검토하는 것보다 쉬운 것은 없습니다. – Pointy

+0

나는 이것을 할 자신을 믿지 않을 것이다. (다른 가능한 문제를 찾을만큼 XML을 알지도 못한다.) ... makeSafeForXML (inString)에서 이것을 수행하는 공통/표준 JS 라이브러리인가? – Seth

+0

또한 우연히 두 번 자격을 얻지 못할까요? 예를 들어 향후 XMLSerializer() + attr() 브라우저가 entitizing을 끝내면 double-escaping이 끝날까요? – Seth

답변

10

함수 sanitizeStringForXML()의 중 하나를 할당하거나 파생 기능 전에 removeInvalidCharacters DOM 트리를 통과 할 수 있으며 자동으로 그렇게 속성과 textNodes을 소독합니다 (이 xmlNode)를 문자열을 정화하는 데 사용할 수있는 그들은 저장하는 것이 안전합니다.

var stringWithSTX = "Bad" + String.fromCharCode(2) + "News"; 
var xmlNode = $("<myelem/>").attr("badattr", stringWithSTX); 

var serializer = new XMLSerializer(); 
var invalidXML = serializer.serializeToString(xmlNode); 

// Now cleanse it: 
removeInvalidCharacters(xmlNode); 
var validXML = serializer.serializeToString(xmlNode); 

은 내가 non-restricted characters section of this wikipedia article에서 문자 목록에이를 기반으로하지만, 보충 비행기는 5 진수 자리 유니 코드 문자를 필요로하며, 지금, 나는 '그래서 자바 스크립트 정규식, 이것에 대한 구문을 포함하지 않는다 m은 (당신이 ... 너무 많은 실종되지 않습니다) 그들을 제거 : 이것은 단지 속성과 textNodes의 nodeValues에서 잘못된 문자를 제거하는 것이

// WARNING: too painful to include supplementary planes, these characters (0x10000 and higher) 
// will be stripped by this function. See what you are missing (heiroglyphics, emoji, etc) at: 
// http://en.wikipedia.org/wiki/Plane_(Unicode)#Supplementary_Multilingual_Plane 
var NOT_SAFE_IN_XML_1_0 = /[^\x09\x0A\x0D\x20-\xFF\x85\xA0-\uD7FF\uE000-\uFDCF\uFDE0-\uFFFD]/gm; 
function sanitizeStringForXML(theString) { 
    "use strict"; 
    return theString.replace(NOT_SAFE_IN_XML_1_0, ''); 
} 

function removeInvalidCharacters(node) { 
    "use strict"; 

    if (node.attributes) { 
     for (var i = 0; i < node.attributes.length; i++) { 
      var attribute = node.attributes[i]; 
      if (attribute.nodeValue) { 
       attribute.nodeValue = sanitizeStringForXML(attribute.nodeValue); 
      } 
     } 
    } 
    if (node.childNodes) { 
     for (var i = 0; i < node.childNodes.length; i++) { 
      var childNode = node.childNodes[i]; 
      if (childNode.nodeType == 1 /* ELEMENT_NODE */) { 
       removeInvalidCharacters(childNode); 
      } else if (childNode.nodeType == 3 /* TEXT_NODE */) { 
       if (childNode.nodeValue) { 
        childNode.nodeValue = sanitizeStringForXML(childNode.nodeValue); 
       } 
      } 
     } 
    } 
} 

참고. 태그 이름이나 속성 이름, 주석 등을 확인하지 않습니다.

+0

실수가있는 경우, 문자 목록에 대한 수정이 감사합니다. :-( – Seth

+0

5 시간 후에도 내 문제를 해결할 수 있습니다. 감사합니다. – MOB