PHP中使用strip_tags提取完整SVG内容的异常问题求助
解决PHP中提取完整SVG内容的问题
你的问题出在strip_tags的使用场景和字符串格式不匹配上,咱们一步步来解决:
为什么原来的方法失效?
- 转义实体的问题:你的字符串里的标签都是HTML转义后的(比如
<svg>),而strip_tags只识别原始的<>标签,所以它根本没把这些当成SVG标签处理,反而错误保留了DOCTYPE的内容。 - 前缀无法处理:开头的
image/svg+xml,不属于HTML标签,strip_tags不会移除它。 - 标签范围有限:你只允许了
<svg>标签,但实际上需要保留内部的<path>,而且strip_tags也没法过滤掉XML声明和DOCTYPE这些非标签内容。
推荐解决方案:用DOMDocument解析(最可靠)
DOM方法能正确处理XML结构,避免正则的局限性,步骤如下:
$original = 'image/svg+xml,<?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="62" height="57"><path fill="none" stroke="#000000" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" d="M 13 5 c -0.02 0.1 -0.39 4.17 -1 6 c -0.67 2.02 -2.57 3.96 -3 6 c -1.15 5.51 -0.64 12.54 -2 18 c -0.84 3.37 -3.95 6.69 -5 10 c -0.85 2.68 -1 9 -1 9"/><path fill="none" stroke="#000000" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" d="M 9 29 c 0.09 0 3.62 0.34 5 0 c 1 -0.25 1.99 -1.84 3 -2 c 2.81 -0.43 10 0 10 0"/><path fill="none" stroke="#000000" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" d="M 29 5 c 0.07 0.21 3.63 8.04 4 12 c 0.9 9.7 0.52 22.2 0 31 c -0.06 1.02 -2 3 -2 3"/><path fill="none" stroke="#000000" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" d="M 59 1 c 0 0.82 -0.53 33.64 0 47 c 0.04 1.02 1.75 2 2 3 c 0.34 1.38 0 5 0 5"/></svg>'; // 1. 把转义的实体还原成原始标签 $decoded = html_entity_decode($original); // 2. 去掉开头的MIME类型前缀 $cleaned = preg_replace('/^image\/svg\+xml,/', '', $decoded); // 3. 用DOM解析提取SVG元素 $dom = new DOMDocument(); // 关闭XML错误提示,避免DOCTYPE带来的警告 libxml_use_internal_errors(true); $dom->loadXML($cleaned); libxml_clear_errors(); // 找到第一个svg元素 $svg = $dom->getElementsByTagName('svg')->item(0); if ($svg) { // 输出完整的SVG内容 $result = $dom->saveXML($svg); // 如果需要再转义回HTML实体(比如要输出到网页),就解开下面这行 // $result = htmlspecialchars($result); echo $result; }
这个方法会精准提取包含所有<path>的完整<svg>标签,完全符合你的需求。
备选方案:正则表达式(适合简单场景)
如果你的SVG结构固定(只有<svg>和<path>),也可以用正则快速匹配:
preg_match('/<svg[^&]+>(?:<path[^&]+>)+<\/svg>/', $original, $matches); if (!empty($matches[0])) { echo $matches[0]; }
不过要注意:如果SVG里出现其他标签或者属性中包含&,正则可能会失效,所以还是DOM方法更稳妥。
内容的提问来源于stack exchange,提问作者itajackass
相关产品推荐
相关产品推荐

