XML转换报错求助:仅IE8及IE7兼容模式可用,transformNode在现代浏览器失效
Hey there, let's dig into this legacy XSLT issue you're facing. That old IE-specific code relies on proprietary APIs modern browsers dropped ages ago—no wonder you're hitting that Unable to get property 'transformNode' of undefined or null reference error. Here's a step-by-step fix to get this working across all modern browsers, while keeping backward compatibility if you still need it for older IE versions.
First, Understand the Root Problems
The original code uses two IE-only features that don't exist in standard browsers:
- The
<xml>element embedded directly in HTML, with IE's specialXMLDocumentproperty to access its content - The
transformNode()method on XML DOM nodes—modern browsers use the standardXSLTProcessorAPI instead
Step-by-Step Solution
1. Replace the Embedded XSLT with a Standard DOM Parsing Approach
Instead of injecting XSLT into an <xml> tag via innerHTML (which only IE understands), we'll build the XSLT string and parse it directly:
// Build your XSLT string (no need for wrapping <xml> tags) const xsltString = ` <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="/"> <xsl:for-each select="/root/month"> <xsl:if test="name='${moName[showMo]}' and year='${showYr}'"> <xsl:value-of select="uta"/> </xsl:if> </xsl:for-each> </xsl:template> </xsl:stylesheet> `; // Set up a clean container for the transformed output gei("calUTA").innerHTML = "<td></td>";
2. Rewrite the loopTrans Function for Cross-Browser Compatibility
We'll detect which API the browser supports and switch between legacy IE methods and modern standards:
function loopTrans(xsltString, targetId, xmlPrefix) { let xmlDOM, xsltDOM; const targetElement = gei(targetId); const xmlElement = gei(`${xmlPrefix}XML`); // Handle XML and XSLT parsing based on browser if (window.ActiveXObject) { // IE fallback: use existing proprietary properties xmlDOM = xmlElement.XMLDocument; // Parse XSLT with IE's ActiveX parser const xsltActiveX = new ActiveXObject("Msxml2.XMLDOM"); xsltActiveX.async = false; xsltActiveX.loadXML(xsltString); xsltDOM = xsltActiveX; } else { // Modern browsers: use standard DOMParser const parser = new DOMParser(); xmlDOM = parser.parseFromString(xmlElement.textContent, "application/xml"); xsltDOM = parser.parseFromString(xsltString, "application/xml"); } // Perform transformation if (xmlDOM.transformNode) { // IE: use legacy transformNode method targetElement.innerHTML = xmlDOM.transformNode(xsltDOM); } else { // Modern browsers: use standard XSLTProcessor const processor = new XSLTProcessor(); processor.importStylesheet(xsltDOM); const resultDocument = processor.transformToDocument(xmlDOM); // Convert result to HTML string const serializer = new XMLSerializer(); targetElement.innerHTML = serializer.serializeToString(resultDocument.documentElement); } } // Call the updated function with our XSLT string loopTrans(xsltString, "calUTA", "big");
3. Verify Your XML Source
Make sure the ${xmlPrefix}XML element (like bigXML) contains raw, valid XML text. In modern browsers, we use textContent to grab the XML string for parsing—avoid adding extra HTML markup inside this element.
Key Changes Explained
- No more embedded
<xml>tags: Modern browsers don't treat these as special, so we parse XSLT and XML directly from strings usingDOMParser. - Conditional API usage: We check for IE's
ActiveXObjectto maintain backward compatibility, while using standard APIs for all other browsers. XSLTProcessorinstead oftransformNode: This is the W3C standard method for XSLT transformations in Chrome, Firefox, Edge, and other modern tools.
Testing
- Try in modern browsers: The standard code path should handle transformations without errors.
- Test in IE8/IE7 mode: The ActiveX fallback will keep the original behavior working as expected.
内容的提问来源于stack exchange,提问作者John Aghadiuno

