繁体   English   中英

BATCH脚本-读取XML并为同一标记/元素返回多个值,并将其作为变量传递

[英]BATCH Script - Read XML and return multiple values for the same tag/element and pass it as variable

这是代码,它仅读取xml文件中的最后一个TargetEndpoint标记,并将输出显示为-Facebook

@echo off
setlocal enableextensions EnableDelayedExpansion
set input="TP.xml"

for /f "tokens=3 delims=<> " %%i in ('type %input% ^|find "TargetEndpoint"') do set "targetsName=%%i"
echo %targetsName%"

我们希望能够读取所有TargetEndpoint标记并输出以将其作为变量数组传递给批处理脚本的功能-Apple,Google,Microsoft,Adobe,Facebook

XML文件供参考:

  <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <Name revision="1" name="myname">
    <ConfigurationVersion majorVersion="4" minorVersion="0"/>
    <Description>myxml</Description>
    <Policies>
        <!--test1 -->
    </Policies> 
    <Resources>
         <!--test1 -->
    </Resources>
    <TargetServers/>
    <TargetEndpoints>
        <TargetEndpoint>Apple</TargetEndpoint>
        <TargetEndpoint>Google</TargetEndpoint>
        <TargetEndpoint>Microsoft</TargetEndpoint>
        <TargetEndpoint>Adobe</TargetEndpoint>
        <TargetEndpoint>Facebook</TargetEndpoint>
    </TargetEndpoints>
    <validate>false</validate>
</Name> 

我建议将您的XML解析为XML,而不是将其标记和刮擦为文本。 如果将其解析为XML,那么脚本的成功与否取决于XML是否被美化,丑化,缩小等。 由于批处理语言没有简单的方法来解释XML DOM,因此可以使用批处理+ JScript混合脚本从Windows脚本宿主借用。 使用.bat扩展名保存并尝试。

@if (@CodeSection == @Batch) @then

@echo off
setlocal

set "XMLfile=test.xml"
set "nodes=TargetEndpoint"

rem // build array of text node values for TargetEndpoint nodes
set "Ubound=-1"

for /f "delims=" %%I in (
    'cscript /nologo /e:JScript "%~f0" "%XMLfile%" "%nodes%"'
) do (
    set "%%I"
    set /a Ubound += 1
)

rem // display array
set %nodes%

rem // demonstrate retrieval of a value
setlocal enabledelayedexpansion
echo Last element: %nodes%[%Ubound%] = !%nodes%[%Ubound%]!
endlocal

goto :EOF
@end // end batch / begin JScript chimera

String.prototype.trim = function() { return this.replace(/^\s+|\s+$/g, ''); }

var DOM = WSH.CreateObject('Microsoft.XMLDOM'),
    args = { file: WSH.Arguments(0), node: WSH.Arguments(1) },
    XPath = "//" + args.node + "/text()";

DOM.load(args.file);
DOM.async = false;
DOM.setProperty('SelectionLanguage', 'XPath');

if (DOM.parseError.errorCode) {
    var e = DOM.parseError;
    WSH.StdErr.WriteLine('Error in ' + args.file + ' line ' + e.line + ' char '
        + e.linepos + ':\n' + e.reason + '\n' + e.srcText);
    WSH.Quit(1);
}

for (var d = DOM.selectNodes(XPath), i = 0; i < d.length; i++) {
    WSH.Echo(args.node + '[' + i + ']=' + d[i].nodeValue.trim());
}

实际上,您可以使用单行代码对PowerShell进行类似的操作。 如果XML的结构是静态的,并且您不需要通过XPath进行搜索,则可以执行以下操作:

powershell "[xml]$x = (gc test.xml); $x.Name.TargetEndpoints.TargetEndpoint"

或者,如果需要XPath来选择TargetEndpoint节点,则:

powershell "select-xml '//TargetEndpoint/text()' test.xml | %{ $_.node.data }"

请注意,PowerShell的XML解析器比Microsoft.XMLDOM COM对象更严格。 上面的示例XML在PowerShell XML解析器中将出错,因为<?xml?>声明前面带有空格。 另一方面,Jscript似乎并不在乎。

您的问题只是一个简单的问题。 您需要在循环内对set和echo命令进行分组,这将在循环执行时打印每个命令。 当前,它仅打印facebook,因为那是它在列表中找到的最后一个,并且循环结束后即存储在变量中。

例如:

    @echo off
setlocal enableextensions EnableDelayedExpansion
set input="TP.xml"

for /F "tokens=3 delims=<>" %%I in ('type %input% ^|find "TargetEndpoint"') do (
    set targetendpoint=%%I
    echo !targetendpoint!
)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM