解析的 XML 文档中的 XPath 错误 (WrongDocumentError)

问题描述 投票:0回答:4

我正在创建适用于 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}]

javascript firefox xpath firefox-addon firefox-addon-sdk
4个回答
1
投票

嗯,例外的名称,

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();

0
投票

parseFromString
返回一个文档对象。
selectSingleNode
不是文档函数。不能使用标准
document.getElementsByClassname
document.getElementById
document.querySelector
选择节点吗?


0
投票

尝试

var window = parsedXml.ownerDocument.defaultView;
var res = window.content.document.evaluate(xpathExpression, parsedXml, null, window.XPathResult.STRING_TYPE , null);

0
投票
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');
© www.soinside.com 2019 - 2024. All rights reserved.