【问题标题】:Proper file transclusion for classic JScript经典 JScript 的正确文件嵌入
【发布时间】:2021-03-01 07:02:16
【问题描述】:

我想要 C 的 #include 指令或 Python 的 import() 函数。如果您认为这不是 Javascript、VBScript 或 JScript.Net 问题,我将不胜感激。我想要 cscript.exe/wscript.exe 运行的 JScript .js 文件中的功能。不是 mshta.exe 运行的 HTA 中的 JScript/JavaScript。到目前为止我能找到的最接近的东西来自here

function Include(jsFile) {
    var fso, f, s;
    fso = new ActiveXObject("Scripting.FileSystemObject"); 
    f = fso.OpenTextFile(jsFile); 
    s = f.ReadAll(); 
    f.Close(); 
    return(s); 
}

这需要用户调用eval(Include("File.js")),这对我来说是不可取的。我更喜欢一个可以拥有干净的include() 函数的解决方案。以下是我目前发现的:

  • 如果JScript 有类似VBScript 的ExecuteGlobal 的功能,那么问题就迎刃而解了。遗憾的是,JScript 只有eval() 函数在本地范围内执行输入字符串。我在上述函数中尝试了return eval(<commands>),但无济于事。
  • 如果可以在 WSH 的 .wsf/.wsc 文件中包含 XSLT,那么可能会在 XML 级别定义 include() 函数,例如(抱歉,我不知道 XML/XSLT,而这只是伪代码)
<xsl:function name="JS:include">
    <xsl:param name="fileName"/>
    <script language="JScript" src="fileName"/>
</xsl:function>
  • 如果 WSH 的 XML 元素具有 .appendChild() 方法,就像 HTA 的 HTML .hta 文件那样,那么我们可以执行类似 (reference) 的操作:
function include(inputFile){
    var head = document.head;
    var script = document.createElement('script');
    script.language = 'JScript';
    script.src = inputFile
    head.appendChild(script);
}

以上选项似乎都不可用。如果您能帮助我了解是否/如何在经典 JScript 中实现干净的 include() 函数,我将不胜感激。提前感谢您的支持。

【问题讨论】:

    标签: xml jscript wsh transclusion wsc


    【解决方案1】:

    如果我理解您想要做的是调用一个 XSL 扩展函数,它是用 JavaScript 编写的。这是一个示例 .wsf,它以 xml 文件和 xsl 文件作为输入,并输出转换后的结果。

    它说明了如何调用 javascript 扩展函数。对于这个例子,javascript 扩展函数是一个“objDate”对象,它可以将 Epoch 日期转换为格式化字符串。

    希望这会有所帮助,否则我已经浪费了我一晚上的时间来帮助你!

    对不起,这很长,但没有其他办法:)

    这是包含的内容...

    完整的 .WSF 文件(保存到 t.wsf) 示例 XML(保存到 t.xml) 示例 XSL(保存到 t.xsl) 输出。

    要运行示例,请确保您已安装 MSXML,然后运行

    cscript t.wsf t.xml t.xsl
    

    示例 t.wsf 文件

    <package>
    <job id="t1">
    <script language="JScript">
    
    try {
        var objArgs = WScript.Arguments;
        if( objArgs.length < 2) {
            WScript.Echo( "Usage: xform.wsf file.xml, file.xsl" );
            WScript.Quit( 1 ); // no FTP
        }
    
        var xml = loadXML( objArgs(0) );
        var xsl = loadXML( objArgs(1) );
        var aParms = new Array();
        aParms["testparm"] = "XSL Rocks!";
        var xmlResult = transform( xml, xsl, aParms );
    
        // just dump out the result
        WScript.Echo( xmlResult.xml );
    } catch ( err ) {
        WScript.Echo( err.description );
    }
    
    // Creates a DOM document, with the proper parameters set, version 1.1
    function newXML() {
        var strDOMObject = "MSXML2.FreeThreadedDOMDocument";
        var xml = new ActiveXObject( strDOMObject );
        xml.setProperty( "SelectionLanguage", "XPath" ); // i.e. not XSLT
        xml.resolveExternals = 0;
        xml.validateOnParse = 0;
        xml.preserveWhiteSpace = true;
    
        try {
            // configure the document to allow for Microsoft extensions within XPath
            xml.setProperty("SelectionNamespaces", " xmlns:ms='urn:schemas-microsoft-com:xslt' xsl='http://www.w3.org/1999/XSL/Transform' :html='http://www.w3.org/1999/xhtml' " ); 
            xml.setProperty("NewParser", true ); // 2 - 4x performance improvement, NO async, NO DTD validation
        } catch (e) {
            delete e;
        }   
        return xml;
    }
    
    // loads XML from disk, with exceptions
    function loadXML( strFileName ) {
        var xml = this.newXML();
        var strErrMsg = '';
        try {
            if( !xml.load( strFileName ) ) {
                processLoadError( xml );
            }
        } catch( e ) {
            strErrMsg = "Error loading " + strFileName + ":" + e.description;
            e.description = strErrMsg;
            throw e;
        }
        return xml;
    }
    
    function processLoadError( xml ) {
        var strErrMsg = '';
        strErrMsg = xml.parseError.reason;
        if( xml.parseError.srcText != "" )
            strErrMsg += "Source: " + xml.parseError.srcText + "\r\n";
        if( xml.parseError.line != 0 )
            strErrMsg += "Line: " + xml.parseError.line + "\r\n";
        if( xml.parseError.linepos != 0 )
            strErrMsg += "Position: " + xml.parseError.linepos + "\r\n";
        throw new Error( xml.parseError.errorCode, strErrMsg ); 
    }
    
    function transform( xml, xsl, aParms ) {
        try {
            var strDOMObject = "MSXML2.FreeThreadedDOMDocument";
            var strTemplateObject = "MSXML2.XSLTemplate";
            var xslt = new ActiveXObject(strTemplateObject );
            var xmlReturn = new ActiveXObject( strDOMObject );
            var xslProc;
            xslt.stylesheet = xsl;
            xslProc = xslt.createProcessor();
            xslProc.input = xml;
    
    
            // create and add in the extension object
            var dt = new objDate();
            xslProc.addObject( dt, "urn:dt");   
    
            if( aParms ) {
                for( key in aParms ) {
                    if( (typeof(aParms[key]) != "undefined") && ( aParms[key] != null ) ) {
                        xslProc.addParameter( key, aParms[key] );
                    }
                }
            }
            xslProc.transform();
            if( !xmlReturn.loadXML( xslProc.output ) ) {
                processLoadError( xmlReturn );
            }
            return xmlReturn;
        } catch( e ) {
            e.description = "Error transforming XML: " + e.description;
            throw e;
        }
    }
    
    
    // Simple Date Object, add in your own methods here...
    function objDate() {
        // Methods, to be called from XSLT
        this.DateParse = objDate_DateParse;
    }
    
    function objDate_DateParse( objNodeList) {
        if( !objNodeList.length ) 
            return ""; // no date from the XSL, return an empty string
    
        // XSL passes in a collection, typically only 1, but for this exmaple, just get the last one
        for( i = 0; i < objNodeList.length; i++ ) {
            var strDate = objNodeList(i).text;
        }
    
        var dt = new Date( parseInt( strDate ) );
        var strReturn = (dt.getMonth() + 1 ) + "/" + dt.getDate() + " " + dt.getHours() + ":" + dt.getMinutes();
        return  strReturn;
    }
    </script> 
    </job>
    </package>
    

    接下来是一个示例 XML,每行都有一个 Epoch @dt。

    <xml>
        <row id='123' dt='1605666152744'/>
        <row id='234' dt='1605766152744'/>
        <row id='345' dt='1605866152744'/>
    </xml>
    

    然后是调用 javascript 扩展对象“dt”的 XSL。请注意,您必须在 XSL 的顶部声明命名空间。

    <?xml version='1.0'?>
    <xsl:stylesheet version="1.0" xmlns:dt="urn:dt" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt">
    <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
    
    <xsl:param name='testparam'/>
    <xsl:variable name='list' select='//row'/>
    
    <xsl:template match='/'>
    <div>
        <h1>Test XSL with Date Extension - <xsl:value-of select='$testparam'/></h1>
        <table class='table'>
            <thead>
                <tr>
                    <th>Name</th>
                    <th>Date</th>
                </tr>
            </thead>
            <tbody>
                <xsl:for-each select='$list'>
                    <tr>
                        <td><xsl:value-of select='@id'/></td>
                        <td><xsl:value-of select='dt:DateParse(  @dt )'/></td>
                    </tr>
                </xsl:for-each>
            </tbody>
        </table>
    </div>
    </xsl:template>
    </xsl:stylesheet>
    

    最后的结果,注意格式化日期,来自 Epoch Dates。

    <div xmlns:dt="urn:dt" xmlns:msxsl="urn:schemas-microsoft-com:xslt">
            <h1>Test XSL with Date Extension - </h1>
            <table class="table">
                    <thead>
                            <tr>
                                    <th>Name</th>
                                    <th>Date</th>
                            </tr>
                    </thead>
                    <tbody>
                            <tr>
                                    <td>123</td>
                                    <td>11/17 21:22</td>
                            </tr>
                            <tr>
                                    <td>234</td>
                                    <td>11/19 1:9</td>
                            </tr>
                            <tr>
                                    <td>345</td>
                                    <td>11/20 4:55</td>
                            </tr>
                    </tbody>
            </table>
    </div>
    

    【讨论】:

    • 哦,是的,您可以将自定义日期(或其他)对象捆绑到另一个文件中,并单独包含它,但它仍然需要作为 XSL 扩展对象进行相当硬编码。祝你好运!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-09-04
    • 2011-09-17
    • 1970-01-01
    • 2017-08-19
    • 2018-02-18
    • 2014-05-02
    • 1970-01-01
    相关资源
    最近更新 更多