JQuery XML解析:替换标签

时间:2010-10-27 19:47:24

标签: jquery xml

我有以下XML:

<?xml version="1.0" encoding="UTF-8" ?>
<text>
    Lorem <foo>ipsum</foo> dolor sit amet.
</text>

我正在尝试使用JQuery解析此XML,并使用<foo>标记替换响应中的<b></b>标记。结果字符串应为"Lorem <b>ipsum</b> dolor sit amet."

我正在对XML执行GET请求:

  $.ajax({
    type: "GET",
    url: "response.xml",
    dataType: "xml",
    success: function(xml){

    }
  });

我已经尝试过这样调用replaceWith函数:

$(xml).find("foo").replaceWith(function(){
    return "<b>" + $(this).text() + "</b>";
});

但是这将完全从xml响应中删除文本。有什么我想念的吗?

编辑:Firebug显示以下错误:

这[0] .innerHTML未定义

4 个答案:

答案 0 :(得分:3)

我建议您使用Web浏览器的XML DOM,而不是滥用jQuery,它是用来处理HTML的。以下是将XML解析为DOM的方法:

var xmlDoc;
if (window.DOMParser)
{
    var parser = new DOMParser();
    xmlDoc = parser.parseFromString(xml, "text/xml");
}
else // Internet Explorer
{
    xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
    xmlDoc.async = "false";
    xmlDoc.loadXML(xml); 
}

// Now do the tedious DOM manipulations on xmlDoc
var foos = xmlDoc.getElementsByTagName('foo');
for (var i = 0; i < foos.length; i++)
{
    var oldElem = foos[i];
    var replacement = xmlDoc.createElement("b");
    replacement.appendChild(xmlDoc.createTextNode(oldElem.childNodes[0].nodeValue));
    oldElem.parentNode.replaceChild(replacement, oldElem);
}

修改

另一种可能性是使用客户端XSLT将XML转换为所需的HTML。使用这样的XSLT文档:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
                xmlns="http://www.w3.org/1999/xhtml">

  <xsl:template match="*">
    <xsl:value-of select="."/>
  </xsl:template>

  <xsl:template match="text">
    <span>
      <xsl:apply-templates/>
    </span>
  </xsl:template>

  <xsl:template match="foo">
    <b>
      <xsl:apply-templates/>
    </b>
  </xsl:template>

</xsl:stylesheet>

您可以将示例输入转换为spanb标记。如果你有很多转换规则,那么XSLT可能比一堆糟糕的DOM操作代码更易于维护。

答案 1 :(得分:1)

这似乎对我在Firebug控制台中直接使用XML字符串起作用:

var xml = $('<?xml version="1.0" encoding="UTF-8" ?><text>Lorem <foo>ipsum</foo> dolor sit amet.</text>');
xml.find('foo').replaceWith(function(){
  console.log(this);
  return '<b>'+$(this).text()+'</b>';
});
console.log(xml);

您的成功功能还会发生什么?

答案 2 :(得分:0)

jQuery是一个基于HTML的库,处理XML(或一般的跨文档脚本)的能力有限。

一些方法可行:find()text()针对XML通常都可以。但是当你返回像<b>foo</b>这样的标记字符串时,jQuery会将其用作HTML内容,并尝试将其写入元素的innerHTML。但是XML文档不是HTML,因此不支持innerHTML,因此jQuery失败。

在任何情况下,您都不希望使用元素text()并将其逐字用作标记。如果该文字包含<&个字符,该怎么办?这会破坏标记并可能为您提供跨站点脚本漏洞。不要使用天真的字符串索引来准备HTML。

相反,使用DOM样式的方法。像replace()这样的jQuery方法可以做到这一点,但是你不能使用简单的replace('<b>'),因为jQuery会再次使用'<b>'并将其转换为当前拥有的HTML粗体元素HTML文档,然后尝试将该HTML元素插入到XML文档中,这将无法正常工作。相反,您需要使用XML DOM手动创建元素:

$(xml).find("foo").each(function() {
    var b= xml.createElement('b');
    this.parentNode.replaceChild(b, this);
    while (this.firstChild)
        b.appendChild(this.firstChild);
});

这会更改XML文档。但是,如果您尝试将XML文档转换为可用的HTML,那么这似乎并没有帮助您。使用序列化程序(依赖于浏​​览器)转换回XML标记会产生不一定与HTML兼容的标记(例如,空标记可能会自动关闭)。

要将XML元素可靠地导入HTML,最好手动完成。 ( importNode,但IE不支持它。)例如:

function xmlToDocument(node, dest) {
    if (node.nodeType===1) {

        // Create HTML element from XML element. Change name if 'foo'.
        //
        var tag= node.tagName.toLowerCase()==='foo'? 'b' : node.tagName;
        var el= document.createElement(tag);
        dest.appendChild(el);

        // Copy attributes
        //
        for (var attri= node.attributes.length; attri-->0;) {
            var attr= node.attributes[attri];
            el.setAttribute(attr.name, attr.value);
        }

        // Copy element contents
        //
        for (var child= node.firstChild; child!==null; child= child.nextSibling)
            xmlToDocument(child, el);

    }
    else if (node.nodeType===3)
        dest.appendChild(document.createTextNode(node.));
}

您知道......在JSON对象中返回一些HTML标记可能更容易。

答案 3 :(得分:-2)

尝试使用

return "<b>" + $(this).html() + "</b>";

相反