web-dev-qa-db-ja.com

JavaScriptを使用してメモリ内にXMLドキュメントを生成する

XMLをサーバーバックエンドに送信する必要があるWebアプリケーションで作業しています。クライアント側でメモリ内にXMLドキュメントを構築したいのですが、無数の文字列を一緒に追加するのではなく、XML操作ルーチンを使用します。 jQueryが私を助けてくれることを願っています。

JavaScriptを使用してこの(おもちゃ)XMLドキュメントを生成する必要があるとしましょう。

<report>
    <submitter>
        <name>John Doe</name>
    </submitter>
    <students>
        <student>
            <name>Alice</name>
            <grade>80</grade>
        </student>
        <student>
            <name>Bob</name>
            <grade>90</grade>
        </student>
    </students>
</report>

まず、「レポート」ルートを使用して、何らかの種類のXMLドキュメントオブジェクトを作成する必要があります。私はこれらのいずれかが近いはずだと思っていますが、どれも適切に動作しない、および/またはオブジェクトを適切に使用する方法を非常に理解することはできません:

function generateDocument1()
{
    var report = $('<report></report>');
    return report;
}

function generateDocument2()
{
    var report = document.implementation.createDocument(null, "report", null);

    return new XMLSerializer().serializeToString(report);   
}

function createXmlDocument(string)
{
    var doc;
    if (window.DOMParser)
    {
        parser = new DOMParser();
        doc = parser.parseFromString(string, "application/xml");
    }
    else // Internet Explorer
    {
        doc = new ActiveXObject("Microsoft.XMLDOM");
        doc.async = "false";
        doc.loadXML(string); 
    }
    return doc;
}

function generateDocument3()
{
    var report = createXmlDocument('<report></report>');

    return report;
}

次に、要素を作成して追加します。それ、どうやったら出来るの?次のようなものだと思います。

function generateReportXml()
{
    // Somehow generate the XML document object with root
    var report = /*???*/;

    // Somehow create the XML nodes
    var submitter = /*???*/;
    var name = /*???*/;

    // Somehow append name to submitter, and submitter to report
    submitter.append(name); /*???*/
    report.append(submitter); /*???*/

    // ... append the rest of the XML

    return report;
}

何か案は?

36
Shaggy Frog

should jQueryを使用してXMLを構築するかどうかに言及せずに、howのアイデアをいくつか示します。

// Simple helper function creates a new element from a name, so you don't have to add the brackets etc.
$.createElement = function(name)
{
    return $('<'+name+' />');
};

// JQ plugin appends a new element created from 'name' to each matched element.
$.fn.appendNewElement = function(name)
{
    this.each(function(i)
    {
        $(this).append('<'+name+' />');
    });
    return this;
}

/* xml root element - because html() does not include the root element and we want to 
 * include <report /> in the output. There may be a better way to do this.
 */
var $root = $('<XMLDocument />');

$root.append
(
    // one method of adding a basic structure
    $('<report />').append
    (
        $('<submitter />').append
        (
            $('<name />').text('John Doe')
        )
    )
    // example of our plugin
    .appendNewElement('students')
);

// get a reference to report
var $report = $root.find('report');

// get a reference to students
var $students = $report.find('students');
// or find students from the $root like this: $root.find('report>students');

// create 'Alice'
var $newStudent = $.createElement('student');
// add 'name' element using standard jQuery
$newStudent.append($('<name />').text('Alice'));
// add 'grade' element using our helper
$newStudent.append($.createElement('grade').text('80'));

// add 'Alice' to <students />
$students.append($newStudent);

// create 'Bob'
$newStudent = $.createElement('student');
$newStudent.append($('<name />').text('Bob'));
$newStudent.append($.createElement('grade').text('90'));

// add 'Bob' to <students />
$students.append($newStudent);

// display the markup as text
alert($root.html());

出力:

<report>
    <submitter>
        <name>John Doe</name>
    </submitter>
    <students>
        <student>
            <name>Alice</name>
            <grade>80</grade>
        </student>
        <student>
            <name>Bob</name>
            <grade>90</grade>
        </student>
    </students>
</report>
26
rath

2番目のアプローチは良い方法のようです。 XMLドキュメントで動作するように設計されています。ドキュメントオブジェクトを作成したら、標準のXML DOM操作メソッドを使用してドキュメント全体を構築します。

// creates a Document object with root "<report>"
var doc = document.implementation.createDocument(null, "report", null);

// create the <submitter>, <name>, and text node
var submitterElement = doc.createElement("submitter");
var nameElement = doc.createElement("name");
var name = doc.createTextNode("John Doe");

// append nodes to parents
nameElement.appendChild(name);
submitterElement.appendChild(nameElement);

// append to document
doc.documentElement.appendChild(submitterElement);

これは少し冗長に見えるかもしれませんが、XMLドキュメントを構築する正しい方法です。 jQueryは実際にはXMLドキュメントを構築しませんが、innerHTMLプロパティに依存して、HTML文字列が与えられたDOMを解析および再構築します。このアプローチの問題は、XMLのタグ名が<table><option>などのHTMLのタグ名と衝突する場合、結果が予測不能になる可能性があることです。 (編集:1.5から jQuery.parseXML() whichdoesが実際にXMLドキュメントを構築し、これらの問題を回避します—解析のみ。)

冗長性を削減するには、小さなヘルパーライブラリを作成するか、ドキュメントを作成するjQueryプラグインを作成します。

再帰的なアプローチを使用してXMLドキュメントを作成するための、迅速で汚れたソリューションを次に示します。

// use this document for creating XML
var doc = document.implementation.createDocument(null, null, null);

// function that creates the XML structure
function Σ() {
    var node = doc.createElement(arguments[0]), text, child;

    for(var i = 1; i < arguments.length; i++) {
        child = arguments[i];
        if(typeof child == 'string') {
            child = doc.createTextNode(child);
        }
        node.appendChild(child);
    }

    return node;
};

// create the XML structure recursively
Σ('report',
    Σ('submitter',
        Σ('name', 'John Doe')
    ),
    Σ('students',
        Σ('student',
            Σ('name', 'Alice'),
            Σ('grade', '80')
        ),
        Σ('student',
            Σ('name', 'Bob'),
            Σ('grade', '90')
        )
    )
);

戻り値:

<report>​
    <submitter>​
        <name>​John Doe​</name>​
    </submitter>​
    <students>​
        <student>​
            <name>​Alice​</name>​
            <grade>​80​</grade>​
        </student>​
        <student>​
            <name>​Bob​</name>​
            <grade>​90​</grade>​
        </student>​
    </students>​
</report>​

例を参照

63
Anurag

Ariel FleslerのXMLWriterコンストラクター関数が、XMLをゼロから(メモリー内に)作成するための良いスタートであることがわかりました。これを見てください。

http://flesler.blogspot.com/2008/03/xmlwriter-for-javascript.html

function test(){    
   // XMLWriter will use DOMParser or Microsoft.XMLDOM
   var v = new  XMLWriter();
   v.writeStartDocument(true);
   v.writeElementString('test','Hello World');
   v.writeAttributeString('foo','bar');
   v.writeEndDocument();
   console.log( v.flush() );
}

結果

<?xml version="1.0" encoding="ISO-8859-1" standalone="true" ?>
<test foo="bar">Hello World</test>

いくつかの注意事項がありますが、文字列をエスケープせず、構文はcoyote ++のugいものになります。

2
Alex Nolasco

JSONを検討しましたか?オブジェクトを使用してデータを保存できます。その後、JSON.stringify(obj);を使用してサーバーに送信できます。

簡単な例

var obj = new student('Alice',80);

function student(a,b){
  this.name=a;
  this.grade=b;
}

function sendToServer(){
  var dataString = JSON.stringify(obj);
  //the HTTP request
}
1
qw3n

目的のXML構造を同じ構造のJavaScriptオブジェクトで表すことができる場合、そのようなオブジェクトを作成し、次の関数を使用してそのオブジェクトをXMLに変換できます。

/*  Arguments:
      name: name of the root XML-element 
      val: the data to convert to XML
    Returns: XML string 
    Example: toXml("root", { items: { item: [1, 2] } })
      returns: "<root><items><item>1</item><item>2</item></items></root>"
*/
function toXml(name, val) {
    const map = {"<":"&lt;", ">":"&gt;", "&":"&amp;", "'":"&apos", '"':"&quot;"};
    if (Array.isArray(val)) return val.map(elem => toXml(name, elem)).join``;
    const content =  Object(val) === val
        ? Object.keys(val).map(key => toXml(key, val[key])).join``
        : String(val).replace(/[<>&'"]/g, m => map[m]);
    return `<${name}>${content}</${name}>`;
}

// Example:
const report = {
    submitter: { name: "John Doe" },
    students: {
        student: [{ name: "Alice", grade: 80 }, 
                  { name: "Bob",   grade: 90 }]
    }
};

console.log(
    '<?xml version="1.0" encoding="UTF-8" standalone="no" ?>' +
    toXml("report", report));
0
trincot