Javascript для добавления раздела cdata на лету?

У меня возникают проблемы со специальными символами, существующими в атрибуте узла xml. Чтобы бороться с этим, я пытаюсь отображать атрибуты как дочерние узлы и, при необходимости, использовать разделы cdata, чтобы обойти специальные символы. Проблема в том, что я не могу правильно добавить раздел cdata к узлу.

Я перебираю атрибуты исходного узла xml и создаю новые узлы. Если attribute.name = "description", я хочу поместить attribute.text() в раздел cdata и добавить новый узел. Вот где я прыгаю по дорожке.

     // newXMLData is the new xml document that I've created in memory
    for (var ctr =0;ctr< this.attributes.length;ctr++){  // iterate over the attributes 
          if( this.attributes[ctr].name =="Description"){   // if the attribute name is "Description" add a CDATA section 
             var thisNodeName =  this.attributes[ctr].name;
               newXMLDataNode.append("<"+thisNodeName +"></"+ thisNodeName +">" );
               var cdata = newXMLData.createCDATASection('test');  // here's where it breaks. 
          } else {
           // It's not "Description" so just append the new node.
            newXMLDataNode.append("<"+ this.attributes[ctr].name +">" + $(this.attributes[ctr]).text() + "</"+ this.attributes[ctr].name +">"   );  
          }        
        } 

Любые идеи? Есть ли другой способ добавить раздел cdata?

Вот примерный фрагмент исходника...

<row 
pSiteID="4" 
pSiteTile="Test Site Name " 
pSiteURL="http://www.cnn.com"
ID="1" 
Description="<div>blah blah blah since June 2007.&amp;nbsp; T<br>&amp;nbsp;<br>blah blah blah blah&amp;nbsp; </div>" 
CreatedDate="2010-09-20 14:46:18" 
Comments="Comments example.&#10;" >

вот что я пытаюсь создать...

<Site>
<PSITEID>4</PSITEID>
<PSITETILE>Test Site Name</PSITETILE>
<PSITEURL>http://www.cnn.com</PSITEURL>
<ID>1</ID>
<DESCRIPTION><![CDATA[<div>blah blah blah since June 2007.&amp;nbsp; T<br>&amp;nbsp;<br>blah blah blah blah&amp;nbsp; </div ]]></DESCRIPTION>
<CREATEDDATE>2010-09-20 14:46:18</CREATEDDATE>
<COMMENTS><![CDATA[ Comments example.&#10;]]></COMMENTS>
</Site>

person Chris G.    schedule 17.01.2011    source источник
comment
Можете ли вы показать XML до и после добавления CDATA?   -  person TJ L    schedule 17.01.2011
comment
Если ваш XML неправильно сформирован, у вас есть ДВЕ проблемы.   -  person drudge    schedule 18.01.2011
comment
Это не очень помогает. Я пытаюсь создать правильно сформированный xml из не очень хорошо сформированного xml. Отсюда CDATA.   -  person Chris G.    schedule 18.01.2011


Ответы (2)


Я была такая же проблема. я пытался добавить CDATA к узлам xml, поэтому я подумал, что это так же просто, как добавить так:

valueNode[0].text = "<![CDATA["+ tmpVal +"]]>";
//valueNode[0] represents "<value></value>"

Это не работает, потому что все это будет интерпретироваться как текст, поэтому ‹(меньше чем) и > (больше чем) будут заменены автоматически.

вам нужно использовать createCDATASection, выполнив следующие действия:

var tmpCdata = $xmlDoc[0].createCDATASection(escape("muzi test 002"));
//i'm also escaping special charactures as well
valueNode[0].appendChild(tmpCdata);

результаты будут:

<value><![CDATA[muzi%20test%20002]]></value>

Brettz9 (в предыдущем ответе) объясняет, как это сделать, но довольно сложно, поэтому я просто хотел добавить свое решение, которое намного проще.

Благодарность,

person zulucoda    schedule 21.06.2011

Не уверен в поддержке браузером document.implementation.createDocument или createCDataSection, но это работает по крайней мере в Mozilla:

<script>

    // Define some helpers (not available IE < 9)
    function parse (str) {
        return new DOMParser().parseFromString(str, 'text/xml').documentElement;
    }
    function ser (dom) {
        return new XMLSerializer().serializeToString(dom);
    }

    // Simulate your XML retrieval
    var row = '<row pSiteID="4" pSiteTile="Test Site Name " pSiteURL="http://www.cnn.com" ID="1" Description="<div>blah blah blah since June 2007.&amp;nbsp; T<br>&amp;nbsp;<br>blah blah blah blah&amp;nbsp; </div>" CreatedDate="2010-09-20 14:46:18" Comments="Comments example.&#10;" />';

    // Hack to convert source to well-formed XML, or otherwise you can't use DOM methods on it which
    // depend on well-formed XML
    row = row.replace(/(=\s*")([\s\S]*?)(")/g, function (n0, n1, n2, n3) {
        return n1+ // Add back equal sign and opening quote
            n2.replace(/</g, '&lt;'). // Create well-formed XML by avoiding less-than signs inside attributes
            replace(/&amp;nbsp;/g, '&amp;#160;')+ // HTML entities (except for gt, lt, amp, quot) must be either converted to numeric character references or your XML must define the same entities
            n3; // Add back closing quote
    });

    // Simulate your retrieval of DOM attributes, though in this context, we're just making attributes into a global
    this.attributes = parse(row).attributes;

    // Simulate your creation of an XML document
    var newXMLData = document.implementation.createDocument(null, 'Site', null);

    // Modify your code to avoid jQuery dependency for easier testing and to 
    // avoid confusion (error?) of having two variables, newXMLData and newXMLDataNode
    for (var ctr =0;ctr< this.attributes.length;ctr++){  // iterate over the attributes 
      if (this.attributes[ctr].name =="Description") {   // if the attribute name is "Description" add a CDATA section 
         var thisNodeName =  this.attributes[ctr].name;
         var str = "<"+thisNodeName +"></"+ thisNodeName +">";
         var node = parse(str);
         var cdata = newXMLData.createCDATASection(this.attributes[ctr].textContent);
         node.appendChild(cdata);
         newXMLData.documentElement.appendChild(node);       
      }
      else {
       // It's not "Description" so just append the new node.
        var str= "<"+ this.attributes[ctr].name +">" + this.attributes[ctr].textContent + "</"+ this.attributes[ctr].name +">";
        newXMLData.documentElement.appendChild(parse(str));
      }
    } 
    // Prove its working (though you may wish to use toUpperCase() if you need the element names upper-cased); 
    // if you need CDATA for Comments, you can follow the pattern above to add support for that too
    alert(ser(newXMLData)); 
</script>
person Brett Zamir    schedule 22.04.2011