2013-02-02 8 views
5

Ich versuche, Benutzereingabe in einem XML-Dokument auf der Client-Seite (Javascript) zu speichern und diese an den Server für die Persistenz zu übertragen.Entfernen von ungültigen Zeichen aus XML vor dem Serialisieren mit XMLSerializer()

Ein Benutzer zum Beispiel eingefügt in Text, der ein STX-Zeichen (0x2) enthalten. Der XMLSerializer hat das STX-Zeichen nicht verlassen und wurde daher nicht in wohlgeformtes XML serialisiert. Oder vielleicht hätte der Aufruf .attr() dem STX-Zeichen entgangen sein sollen, aber in jedem Fall wurde ungültiges XML erzeugt.

ich die Ausgabe von in-Browser XMLSerializer zu finden() ist nicht immer gut ausgebildet ist, (und erfüllen nicht einmal die eigenen DOMParser Browser()

Dieses Beispiel zeigt, dass das STX-Zeichen ist nicht richtig codiert durch 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> 

Wie soll ich ein XML-Dokument im Browser-Konstrukt (mit von beliebiger Benutzereingabe bestimmt params), so dass es immer gut gebildet werden (alles entging richtig)? Ich muss IE8 oder IE7 nicht unterstützen.

(Und ja, ich validiere die XML auf der Serverseite, aber wenn der Browser dem Server ein Dokument übergibt, das nicht wohlgeformt ist, ist es das Beste, was der Server tun kann, es abzulehnen, was für die Armen nicht hilfreich ist Benutzer)

+0

Ich bin mir nicht sicher, ob es viel einfacher ist, als die Quellzeichenfolge Zeichen für Zeichen durchzugehen und bei Bedarf zu Entitäten zu übersetzen. – Pointy

+0

Ich würde mir nicht trauen, dies zu tun (ich kenne XML nicht gut genug, um nach anderen möglichen Problemen zu suchen) ... ist eine gemeinsame/Standard-JS-Bibliothek, um dies für mich makeSafeForXML (inString) zu tun? – Seth

+0

Würden Sie nicht zufällig zufällig doppelt vergeben? Zum Beispiel, wenn in einem zukünftigen Browser XMLSerializer() + attr() enden wird, was zu einem doppelten Escaping führt? – Seth

Antwort

10

Hier ist eine Funktion sanitizeStringForXML() die Saiten vor der Zuweisung reinigen kann entweder verwendet oder ein Derivat Funktion removeInvalidCharacters (XmlNode) die einen DOM-Baum übergeben werden kann und automatisch desinfiziert Attribute und textNodes so Sie sind sicher zu lagern.

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); 

I basiert diese auf einer Liste von Zeichen aus dem non-restricted characters section of this wikipedia article, aber die zusätzlichen Flugzeuge benötigen 5-hex-stellige Unicode-Zeichen und die Javascript regex enthält keine Syntax für diese, so jetzt, ich m Strippen sie gerade aus (Sie sind nicht zu viel fehlt ...):

// 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); 
       } 
      } 
     } 
    } 
} 

Beachten Sie, dass dies nur entfernt ungültige Zeichen aus nodeValues ​​von Attributen und textNodes. Es überprüft keine Tag-Namen oder Attributnamen, Kommentare, usw.

+0

Korrekturen an der Character List geschätzt, wenn es Fehler gäbe, wüsste ich nicht :-( – Seth

+0

löse mein Problem nach 5hr Suche, danke – MOB

Verwandte Themen