I'm creating a Firefox for Android extension and I have a problem with a XML document retrieved from a XMLHttpRequest
: I can't find a way to select a node. The better solution I found is this, but I got this error when selecting with xpath on the document:
我正在创建一个Firefox for Android扩展,但我在处理从XMLHttpRequest检索到的XML文档时遇到了一个问题:我找不到选择节点的方法。我找到的更好的解决方案是这样的,但在文档上选择with XPath时出现以下错误:
WrongDocumentError: Node cannot be used in a document other than the one in which it was created
This is my code:
这是我的代码:
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);
If I replace the "evaluate" with the next line:
如果我用下一行替换“EVALUE”:
var res = parsedXml.selectSingleNode(xpathExpression);
Then I get the following error:
然后,我得到以下错误:
[JavaScript Error: "parsedXml.selectSingleNode is not a function"
{file: "resource://gre/modules/addons/XPIProvider.jsm ->
jar:file:///data/data/org.mozilla.fennec/files/mozilla/ggz9zzjr.default/extensions/[email protected]!/bootstrap.js"
line: 61}]
更多回答
Well, the name of the exception, WrongDocumentErrort
gave it away. You're trying to call .evaluate()
on a DOM (Document
) that does not belong to the same Document .evaluate()
is bound to.
好吧,这个例外的名字,WrongDocumentErrot泄露了它。您正在尝试对不属于.valuate()绑定到的同一文档的DOM(文档)调用.valuate()。
The nsIDOMParser
will actually return a new XMLDocument
that has an .evaluate()
itself, which you'll have to use.
NsIDOMParser实际上将返回一个新的XMLDocument,该XMLDocument本身有一个.valuate(),您必须使用它。
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);
Instead using nsIDOMParser
, since your content seems to be originating from XHR
anyway, and seems to be (X)HTML (indicated by your expression), it might be better to use XHR.responseType = "document"
instead, which will parse a DOM from the response using the HTML parser.
不使用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
returns a document object. selectSingleNode
is not a document function. Can't you select a node using the standard document.getElementsByClassname
, document.getElementById
, or document.querySelector
?
ParseFromString返回一个Document对象。SelectSingleNode不是单据函数。不能使用标准的Document.getElementsByClassname、Document.getElementByID或Document.querySelector选择节点吗?
try
试试看
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');
更多回答
You need to edit your answer and provide explanation to the code, explain the thought process and why it is solving the problem according to you.
你需要编辑你的答案并对代码进行解释,解释你的思维过程以及它为什么会根据你的想法解决问题。
我是一名优秀的程序员,十分优秀!