xml捕获需区分xhr/fetch响应与dom嵌入两类来源:前者须拦截网络请求并解析响应体,后者应直接提取textcontent;混用方法将导致失败。

XML 捕获必须区分来源:XHR 还是 DOM?
浏览器插件无法“全局监听所有 XML”,必须明确目标来源。常见两类:一是页面通过 fetch 或 XMLHttpRequest 加载的 XML 响应(如 RSS、SOAP 接口);二是页面 DOM 中已存在的 <?xml> 声明或 <root><item>...</item></root> 结构。前者需拦截网络请求,后者可直接查询 DOM —— 方法完全不同,混用会导致捕获失败。
- DOM 中的 XML 通常只是普通 HTML 元素(如
<pre class="brush:php;toolbar:false;"></pre>里放的 XML 字符串),没有解析为 XML 文档对象,不能用responseXML - XHR/fetch 的 XML 响应,只有在
responseType === 'document'或服务端返回Content-Type: application/xml且浏览器自动解析时,才可能拿到responseXML - 现代 fetch 默认不解析 XML,
response.text()是最稳妥的获取原始 XML 字符串方式
拦截 XHR/fetch 并提取 XML 响应体
需在 content script 中重写原生方法,捕获响应内容。注意:fetch 拦截比 XHR 更复杂,因它是 Promise 驱动,需包装 response.clone() 避免 body 被读取多次。
const originalFetch = window.fetch;
window.fetch = function(...args) {
return originalFetch(...args).then(response => {
// 只处理明确返回 XML 的响应
const contentType = response.headers.get('content-type');
if (contentType && /application\/xml|text\/xml/i.test(contentType)) {
const cloned = response.clone();
cloned.text().then(xmlStr => {
// 此处发送 XML 字符串到后台脚本或上传接口
chrome.runtime.sendMessage({
type: 'xml-captured',
url: response.url,
xml: xmlStr.slice(0, 102400) // 限制长度防爆内存
});
}).catch(() => {});
}
return response;
});
};
- 不要在 fetch 拦截中直接调用
response.text()后返回新 Response —— 会破坏原始响应流 -
chrome.runtime.sendMessage需在 manifest.json 中声明"externally_connectable"或仅用于内部通信 - 部分站点使用
blob:URL 或 Service Worker 拦截请求,此时 content script 无法捕获,需改用webRequestAPI(需"webRequest"权限和"host_permissions")
从 DOM 提取 XML 字符串的可靠方式
当 XML 以文本形式嵌入 HTML(如 <script type="application/xml"></script>、<pre class="xml"></pre>、或注释节点),用 textContent 最安全。避免用 innerHTML,防止误解析标签。
下载 Comet AI 浏览器,体验由 Perplexity AI 驱动的革命性上网方式。内置 AI 助手可实时总结网页、跨标签页对比信息、自动执行任务。告别繁琐操作,让 AI 成为你的浏览副驾,大幅提升研究与工作效率。支持 Windows、macOS、Android 和 iOS。
// 匹配常见的 XML 容器
const xmlCandidates = [
'script[type="application/xml"]',
'script[type="text/xml"]',
'pre.xml',
'code.xml',
'textarea[lang="xml"]'
].map(sel => document.querySelectorAll(sel)).flat();
xmlCandidates.forEach(el => {
let xmlStr = el.textContent.trim();
// 简单校验:开头是否含 <?xml 或 <root 类似结构
if (/^<\?xml\s|^\s*<\w+[\s>]/.test(xmlStr)) {
chrome.runtime.sendMessage({
type: 'xml-from-dom',
selector: el.outerHTML.substring(0, 50),
xml: xmlStr.slice(0, 102400)
});
}
});
- DOM 提取无法捕获动态生成的 XML(如 JS 拼接后写入
innerHTML但未挂载到文档) - 若 XML 被压缩成一行且无换行,正则
/^ 仍有效;但纯二进制 XML(如 gzip 压缩)无法通过 DOM 提取 - 注意 CSP 限制:某些站点禁止内联脚本执行,需将逻辑注入到
run_at: "document_idle"的 content script
上传前必须处理的三个实际问题
直接 fetch(uploadUrl, { method: 'POST', body: xmlStr }) 很容易失败。真实环境中需确认以下三点:
- 服务端是否要求
Content-Type: application/xml?还是接受text/plain或表单字段?不匹配会返回 400 - XML 字符串是否含非法控制字符(如 \u0000–\u0008)?上传前建议用
xmlStr.replace(/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/g, '')清理 - 跨域上传时,若服务端未设置
Access-Control-Allow-Origin,需走 background script 中转(background 不受 CORS 限制)
最易被忽略的是编码一致性:XML 声明中的 encoding="GBK" 和实际传输字节不匹配,会导致服务端解析乱码。插件中统一用 UTF-8 处理和上传,除非服务端明确要求其他编码。










