首页 > 解决方案 > jQuery:从具有多个节点的 HTML 字符串中提取最顶层的 SVG 元素

问题描述

这个问题这个问题很相似,但是答案并没有产生一种干净、一致的方法来在不同的 HTML 字符串中找到最顶层的 SVG 元素。

目标是从 HTML 字符串中提取最顶层的 SVG 元素。

$(htmlString).find("svg")不起作用。

$($.parseHTML(htmlString))仅生成一组 jQuery 对象,但目标是将其htmlString转换为一个 jQuery 对象,您可以在其中执行查找和检索最顶层的 SVG 元素。

示例 HTML 字符串:

<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Generator: Adobe Illustrator 18.1.1, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" id="Capa_1" x="0px" y="0px" viewBox="0 0 424 424" style="enable-background:new 0 0 424 424;" xml:space="preserve" width="512px" height="512px">
<g>
    <g>
        <path d="M35,89C15,89,0,74,0,54s15-36,35-36h353c20,0,36,16,36,36s-16,35-36,35H35z" fill="#7c7a7d"/>
        <path d="M388,176c20,0,36,16,36,36s-16,35-36,35H35c-20,0-35-15-35-35s15-36,35-36H388z" fill="#7c7a7d"/>
        <path d="M388,335c20,0,36,15,36,35s-16,36-36,36H35c-20,0-35-16-35-36s15-35,35-35H388z" fill="#7c7a7d"/>
    </g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
</svg>

$($.parseHTML(htmlString)) 的结果,其中 htmlString 是上面的字符串:

$($.parseHTML(htmlString))

w.fn.init(6) [comment, text, comment, text, svg#Capa_1, text]
0: comment
1: text
2: comment
3: text
4: svg#Capa_1
5: text
length: 6

标签: javascriptjqueryhtmlsvg

解决方案


你不能find在结果上使用,因为你给 jQuery 的标记并不代表一棵树:Doctype 和 comments 节点是你的<svg>.

因此,您需要filterjQuery 条目才能仅保留 svg 节点:

const $svg = $(`<?xml version="1.0" encoding="utf-8"?>
<!-- comment1  -->
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" id="Capa_1" x="0px" y="0px" viewBox="0 0 424 424">
  <g>
    <g>
      <path d="M35,89C15,89,0,74,0,54s15-36,35-36h353c20,0,36,16,36,36s-16,35-36,35H35z" fill="#7c7a7d"/>
      <path d="M388,176c20,0,36,16,36,36s-16,35-36,35H35c-20,0-35-15-35-35s15-36,35-36H388z" fill="#7c7a7d"/>
      <path d="M388,335c20,0,36,15,36,35s-16,36-36,36H35c-20,0-35-16-35-36s15-35,35-35H388z" fill="#7c7a7d"/>
    </g>
  </g>
</svg>`)
.filter((i, el) => $(el).is('svg'));

console.log($svg.attr('id'));
$svg.find('path').attr('fill', 'red');
$('body').append($svg);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

现在,您可能还想使用本机 DOMParser,它在处理命名空间方面可能比 jQuery 更好。从那里,您将拥有一个 XMLDocument,documentElement它将成为您的<svg>节点。然后,您将能够从 jQuery 处理它:

const str = `<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" id="Capa_1" x="0px" y="0px" viewBox="0 0 424 424">
  <g>
    <g>
      <path d="M35,89C15,89,0,74,0,54s15-36,35-36h353c20,0,36,16,36,36s-16,35-36,35H35z" fill="#7c7a7d"/>
      <path d="M388,176c20,0,36,16,36,36s-16,35-36,35H35c-20,0-35-15-35-35s15-36,35-36H388z" fill="#7c7a7d"/>
      <path d="M388,335c20,0,36,15,36,35s-16,36-36,36H35c-20,0-35-16-35-36s15-35,35-35H388z" fill="#7c7a7d"/>
    </g>
  </g>
</svg>`;

const doc = (new DOMParser).parseFromString(str, 'image/svg+xml');
// use the second argument (context) of jQuery()
const $svg = $('svg', doc);
console.log($svg.attr('id'));
$svg.find('path').attr('fill', 'red');
$('body').append($svg);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>


推荐阅读