我正在创建适用于 Android 的 Firefox 扩展,但从
XMLHttpRequest
检索 XML 文档时遇到问题:我找不到选择节点的方法。我找到的更好的解决方案是这样的,但是在文档上使用xpath选择时出现这个错误:
WrongDocumentError: Node cannot be used in a document other than the one in which it was created
这是我的代码:
var parser = Cc["@mozilla.org/xmlextras/domparser;1"].createInstance(Ci.nsIDOMParser);
var parsedXml = parser.parseFromString(xmlhttp.responseText, "text/xml");
var xpathExpression = "//td[contains(.,'Raw text')]/../td[2]/pre";
var res = window.content.document.evaluate(xpathExpression, parsedXml, null, window.XPathResult.STRING_TYPE , null);
如果我用下一行替换“评估”:
var res = parsedXml.selectSingleNode(xpathExpression);
然后我收到以下错误:
[JavaScript 错误:“parsedXml.selectSingleNode 不是函数” {文件:“resource://gre/modules/addons/XPIProvider.jsm -> jar:file:///data/data/org.mozilla.fennec/files/mozilla/ggz9zzjr.default/extensions/[email protected]!/bootstrap.js" 行:61}]
嗯,例外的名称,
WrongDocumentErrort
泄露了。您尝试在不属于 .evaluate()
绑定到的同一个文档的 DOM (Document
) 上调用 .evaluate()
。
nsIDOMParser
实际上会返回一个新的XMLDocument
,它本身有一个.evaluate()
,你必须使用它。
var parser = Cc["@mozilla.org/xmlextras/domparser;1"].
createInstance(Ci.nsIDOMParser);
var parsedDoc = parser.parseFromString(
'<?xml version="1.0"?>\n<doc><elem>Raw text</elem></doc>',
"text/xml");
var xpathExpression = "//elem[contains(.,'Raw text')]";
var res = parsedDoc.evaluate(
xpathExpression,
parsedDoc,
null,
XPathResult.STRING_TYPE,
null);
console.log(res, res.stringValue);
而不是使用
nsIDOMParser
,因为无论如何你的内容似乎都源自 XHR
,并且似乎是 (X)HTML(由你的表达式表示),所以最好使用 XHR.responseType = "document"
来代替,它将解析使用 HTML 解析器从响应中获取 DOM。
var req = new XMLHttpRequest();
req.onload = function() {
var doc = req.response;
var h1 = doc.evaluate("//h1", doc, null, XPathResult.STRING_TYPE, null);
console.log(h1.stringValue);
// Alternative in some cases
h1 = doc.querySelector("h1");
console.log(h1.textContent);
};
req.open("GET", "http://example.org/");
req.responseType = "document"; // Parse as text/html
req.send();
parseFromString
返回一个文档对象。 selectSingleNode
不是文档函数。不能使用标准 document.getElementsByClassname
、document.getElementById
或 document.querySelector
选择节点吗?
尝试
var window = parsedXml.ownerDocument.defaultView;
var res = window.content.document.evaluate(xpathExpression, parsedXml, null, window.XPathResult.STRING_TYPE , null);
const crypto = require('crypto');
const fs = require('fs');
const { v4: uuidv4 } = require('uuid');
//XPATH PARSE: ERROR TRY DIFFERENT APPROACH
//TJS: MAKE SURE TO USE '\n' +
const ts = new Date().toISOString();
console.log(ts);
// Load your private key and XML content
const privateKeyPem = fs.readFileSync('UAT_Document_Signer.pem', 'utf8');
const xmlContent = '<content>some content</content>';
// Load your X.509 certificate
const x509CertificatePem = fs.readFileSync('tjscertificate.crt', 'utf8');
// Remove "-----BEGIN CERTIFICATE-----" and "-----END CERTIFICATE-----" from the certificate
const cleanedX509CertificatePem = x509CertificatePem
.replace(/-----BEGIN CERTIFICATE-----/g, '')
.replace(/-----END CERTIFICATE-----/g, '')
.replace(/\s/g, ''); // Remove all whitespace, including line breaks
// Parse the X.509 certificate to extract issuer name and serial number
const x509IssuerName = 'CN=esign, OU=esign, O=esign, L=India, C=91'; // Extract this from your CRT file
const x509SerialNumber = '56046136974634'; // Extract this from your CRT file
// Create a private key object
const privateKey = crypto.createPrivateKey(privateKeyPem);
// Calculate the message digest (SHA-256 hash) of the XML content
const md = crypto.createHash('sha256');
md.update(xmlContent, 'utf8');
const messageDigest = md.digest();
// Create the SignedInfo element with SHA-256 digest
const signedInfoPrefix = '<ds:SignedInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">\n';
const signedInfo =
signedInfoPrefix +
'<ds:CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"></ds:CanonicalizationMethod>\n' +
'<ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha256"></ds:SignatureMethod>\n' +
'<ds:Reference URI="">\n' +
'<ds:Transforms>\n' +
'<ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"></ds:Transform>\n' +
'<ds:Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments"></ds:Transform>\n' +
'</ds:Transforms>\n' +
`<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#sha256"></ds:DigestMethod>\n` +
`<ds:DigestValue>${messageDigest.toString('base64')}</ds:DigestValue>\n` +
'</ds:Reference>\n' +
'</ds:SignedInfo>';
// Calculate the SHA-256 hash of the SignedInfo element
const md2 = crypto.createHash('sha256');
md2.update(signedInfo, 'utf8');
const signatureDigest = md2.digest();
// Sign the SHA-256 hash of the SignedInfo element with the private key
const signature = crypto.sign('sha256WithRSAEncryption', signatureDigest, {
key: privateKey,
padding: crypto.constants.RSA_PKCS1_PSS_PADDING,
saltLength: crypto.constants.RSA_PSS_SALTLEN_DIGEST,
});
// Encode the signature in base64
const base64Signature = signature.toString('base64');
// Create the Signature element
const signatureXml = `
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
<SignedInfo>
${signedInfo}
</SignedInfo>
<SignatureValue>${base64Signature}</SignatureValue>
<KeyInfo>
<X509Data>
<X509Certificate>${cleanedX509CertificatePem}</X509Certificate>
<X509IssuerSerial>
<X509IssuerName>${x509IssuerName}</X509IssuerName>
<X509SerialNumber>${x509SerialNumber}</X509SerialNumber>
</X509IssuerSerial>
</X509Data>
</KeyInfo>
</Signature>`;
// Create the Esign element and embed the Signature
const esignXml = `
<Esign AuthMode="1" aspId="mQ3SY2lvVg9qUAauq9ztMACHMZwfDxym" ekycId="" ekycIdType="A" responseSigType="pkcs7" responseUrl="http://localhost:8080/esignAsp-0.0.1-SNAPSHOT/res/dummy@1@1" sc="Y" ts="2023-09-08T10:25:51" txn="94140c33-074b-4c2e-8e20-a167b17da234" ver="2.1">
<Docs>
<InputHash docInfo="Test" hashAlgorithm="SHA256" id="1">620952d725b5c065df94ac55ff34e4a9311b5541a26787e884db93719478a95f</InputHash>
</Docs>
${signatureXml}
</Esign>`;
// Create the final XML document
const finalXml = `<?xml version="1.0" encoding="UTF-8" standalone="no"?>${esignXml}`;
// Save the final XML document to a file or process it as needed
fs.writeFileSync('e.xml', finalXml);
console.log('XML with embedded signature and X.509 certificate saved to signed-esign-xml-with-certificate.xml');