这可能需要考虑很多,但我尽我所能尽力解释。
我有一个输入/上传字段,用户可以在其中提供XML文件。该文件如下所示。
<node begin="0" cat="smain" end="10" id="1" rel="--">
<node begin="0" cat="np" end="5" id="2" rel="su">
<node begin="0" end="1" id="3" lemma="de" lwtype="bep" naamval="stan" npagr="rest" pos="det" postag="LID(bep,stan,rest)" pt="lid" rel="det" root="de" word="De" />
<node begin="1" end="2" genus="zijd" getal="ev" graad="basis" id="4" lemma="helft" naamval="stan" ntype="soort" pos="noun" postag="N(soort,ev,basis,zijd,stan)" pt="n" rel="hd" root="helft" word="helft" />
<node begin="2" cat="pp" end="5" id="5" rel="mod">
<node begin="2" end="3" id="6" lemma="van" pos="prep" postag="VZ(init)" pt="vz" rel="hd" root="van" vztype="init" word="van" />
<node begin="3" cat="np" end="5" id="7" rel="obj1">
<node begin="3" buiging="met-e" end="4" id="8" lemma="al" naamval="stan" npagr="agr" pdtype="det" pos="det" positie="prenom" postag="VNW(onbep,det,stan,prenom,met-e,agr)" pt="vnw" rel="det" root="alle" vwtype="onbep" word="alle" />
<node begin="4" buiging="met-e" end="5" getal-n="mv-n" graad="basis" id="9" lemma="werkloos" pos="adj" positie="nom" postag="ADJ(nom,basis,met-e,mv-n)" pt="adj" rel="hd" root="werkloos" word="werklozen" /></node>
</node>
</node>
</node>
我现在要做的是将该文件转换为列表,这意味着所有node
成为li
。我尝试使用以下代码,但控制台返回Uncaught TypeError: Cannot read property 'createDocumentFragment' of undefined
。
$("#xml-input").html($(this).html().replace(/node/g,"li"));
此外,如果我可以使用当然不会产生有效HTML的列表替换节点。 (仅仅找到替换会导致li&gt; li&gt; li没有任何子列表。)
我认为这可以通过以下一些jQuery来解决:
$("li").each(function() {
var $this = $(this);
if ($this.parent().is("li")) {
$this.before("<ol>");
$this.siblings(":last").after("</ol>");
}
});
问题在于,在运行该代码片段之前,浏览器已经自动将错误的HTML转换为正确的HTML。即而不是像这样的东西:
<li>Item 1
<li>Item 2
<li>Item 3</li>
</li>
</li>
浏览器将其修复为:
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
因此,对我们生成的HTML运行jQuery似乎是不可能的。
我想做的其他事情是用数据属性替换属性(例如begin,buiging,end,cat et cetera)。这会产生data-begin
,data-cat
,data-end
等等。我会在整个代码块上运行replace
,但我不能:某些节点可能包含实际文本,例如&#34;开始&#34;我不想将文本替换为data-begin
,只有属性。我猜测正则表达式的替换应该这样做:将<node
视为起点,将>
视为结束点。然后替换=
之前的所有内容,其中字符串本身前面有data-
。不幸的是,我缺乏正则表达式的经验来完成这项工作。
最后,我想将完全彻底检查的HTML添加到另一个div中。像这样:
$("#xml-input").contents().clone().appendTo("#the-list");
理想情况下,最终结果如下:
<li data-begin="0" data-cat="smain" data-end="10" data-id="1" data-rel="--">
<ol>
<li data-begin="0" data-cat="np" data-end="5" data-id="2" data-rel="su">
<ol>
<li data-begin="0" data-end="1" data-id="3" data-lemma="de" data-lwtype="bep" data-naamval="stan" data-npagr="rest" data-pos="det" data-postag="LID(bep,stan,rest)" data-pt="lid" data-rel="det" data-root="de" data-word="De" />
<li data-begin="1" data-end="2" data-genus="zijd" data-getal="ev" data-graad="basis" data-id="4" data-lemma="helft" data-naamval="stan" data-ntype="soort" data-pos="noun" data-postag="N(soort,ev,basis,zijd,stan)" data-pt="n" data-rel="hd" data-root="helft" data-word="helft" />
<li data-begin="2" data-cat="pp" data-end="5" data-id="5" data-rel="mod">
<ol>
<li data-begin="2" data-end="3" data-id="6" data-lemma="van" data-pos="prep" data-postag="VZ(init)" data-pt="vz" data-rel="hd" data-root="van" data-vztype="init" data-word="van" />
<li data-begin="3" data-cat="np" data-end="5" data-id="7" data-rel="obj1">
<ol>
<li data-begin="3" data-buiging="met-e" data-end="4" data-id="8" data-lemma="al" data-naamval="stan" data-npagr="agr" data-pdtype="det" data-pos="det" data-positie="prenom" data-postag="VNW(onbep,det,stan,prenom,met-e,agr)" data-pt="vnw" data-rel="det" data-root="alle" data-vwtype="onbep" data-word="alle" />
<li data-begin="4" data-buiging="met-e" data-end="5" data-getal-n="mv-n" data-graad="basis" data-id="9" data-lemma="werkloos" data-pos="adj" data-positie="nom" data-postag="ADJ(nom,basis,met-e,mv-n)" data-pt="adj" data-rel="hd" data-root="werkloos" data-word="werklozen" />
</ol>
</li>
</ol>
</li>
</ol>
</li>
</ol>
</li>
我希望一切都清楚。如果没有,请评论。这是一个fiddle来玩。
考虑到@ CBroe的评论和an answer on another question我尝试了jQuery的parseXML()函数,但很快就遇到了麻烦。我无法将node
替换为li
,并且附加不会按正确的顺序发生。这是another fiddle。
var xml = $("#xml-input").html(),
xmlParsed = $.parseXML(xml),
xmlObject = $(xmlParsed);
function output(nodes) {
nodes.each(function () {
output($(this).children('node'));
$(this).replaceWith(function () {
return $("<li />", {
html: this.html()
});
}).appendTo("#the-list");
});
}
output(xmlObject.children('node'));
答案 0 :(得分:1)
好的,所以这是我修改过的函数版本http://jsfiddle.net/87sr0dn7/9/:
function output(nodes) {
var newList = $("<ol>");
nodes.each(function (x, e) {
var newLI = $("<li>");
for (var i = 0, l = e.attributes.length, a=null; i < l; i++) {
a = e.attributes[i];
newLI.attr("data-"+a.nodeName, a.nodeValue);
newLI.append("data-"+a.nodeName + '=' + a.nodeValue + ' ');
}
newLI.append(output($(this).children('node')));
newList.append(newLI);
});
return newList;
}
正如我所说的,我已经在这里进行了“真正的递归” - 你有一个嵌套在未知数量级别上的node
个元素的结构,所以递归是要走的路。
首先,创建一个新的ol
元素,然后循环当前级别的所有node
元素。
在每次循环迭代中,创建节点的新li
元素,然后在节点的所有属性上有另一个循环 - 正如我所说,我在“vanilla JS”中完成了这个,因为我可以找不到在jQuery中循环遍历节点的所有属性的简单方法,并且在JavaScript的DOM实现中,这已经有点“内置”了。因此,对于每个属性,都会获取其名称和值,并将li
添加为具有给定值的新data_…
属性。
然后跟随对当前节点的子节点的递归调用,该节点为其下面的节点返回ol
/ li
集,并且该调用的结果被附加到{{ 1}},之前它本身被附加到我们在开头创建的li
。最后,返回新的ol
列表......
如果您只想将一个特定属性的值作为ol
的文本内容,那么只需检查当前处理的属性的li
是否是您要查找的属性 - 如果是这样,它会附加到nodeName
的HTML内容中,否则不会:
li
http://jsfiddle.net/87sr0dn7/10/
结果看起来有点奇怪,因为空的if (a.nodeName == "word") {
newLI.append("data-" + a.nodeName + '=' + a.nodeValue + ' ');
}
元素(对于没有li
属性的节点)现在根本没有直接文本内容(仅{{1}多个word
显示在一行...但是根据您的需要格式化这是另一回事。 (此外,这可以通过f.e.简单地在每个li
中放置一个不间断的空格来开始,http://jsfiddle.net/87sr0dn7/11/)