使用Powershell使用Foreach修改多个XML文档

时间:2017-02-14 20:47:39

标签: xml powershell

我创建了一个脚本来遍历我们的用户目录并修改XML文档以更改应用程序中的设置。通常当我使用foreach时,它会使我的变量=来自集合的一个项目。相反,此脚本会将$XMLPaths中的所有内容放入我的$Path变量。

$XMLPaths = Get-ChildItem \\DFSRoot\DFSShare\view\Profiles\*\AppData\Roaming\Trillian\ -Recurse -Force |
            Where-Object {$_.Name -contains 'Events.xml'} |
            Select FullName |
            FT -HideTableHeaders |
            Out-String

foreach ($Path in $XMLPaths) {
  $xml = [xml](Get-Content $Path)
  $node = $xml.events.prefs.setting | Where {$_.Name -eq 'Sounds'}
  $node.value = '1'
  $XML.Save($Path)
  $Path
  $node
}

这是我正在使用的XML文档。

<?xml version="1.0" encoding="utf-8" ?>
    <!DOCTYPE events
        PUBLIC "--//IETF//DTD RFCxxxx XEVENTS 1.0//EN" "xevents.dtd">

<!-- WARNING: This is a generated file by Trillian.  Do not update while -->
<!--          Trillian is running otherwise updates will be erased       -->

    <events>
        <version>1.0</version>
        <Prefs>
            <setting name="idle" value="1"/>
            <setting name="sounds" value="1"/>
            <setting name="sounds_away" value="1"/>
            <setting name="sounds_suppress" value="1"/>
            <setting name="automatic_outbound" value="1"/>
            <setting name="hide_disabled" value="1"/>
            <setting name="video_capture" value="1"/>
            <setting name="buzz_sound" value="1"/>
            <setting name="game_status" value="0"/>
            <setting name="awaymessage_song" value="0"/>
            <setting name="awaymessage_autosave" value="1"/>
            <setting name="awaymessage_update2" value="1"/>
            <setting name="away_autoresponse" value="0"/>
        </Prefs>
        <AwayList>
            <AwayGroup name="Root">
                <AwayMessage label="Set%20all%20Do%20Not%20Disturb" text="" awayState="1" awayMenu="1" autoRespond="0" system="1">
                    <Status medium="ASTRA" type="Do%20Not%20Disturb"/>
                </AwayMessage>
                <AwayMessage label="Set%20all%20Offline" text="" awayState="1" awayMenu="0" autoRespond="1" system="1">
                    <Status medium="ASTRA" type="Offline"/>
                </AwayMessage>
                <AwayMessage label="Set%20all%20Away" text="Away%20since%20%25time%25%20%28%25timeZoneOffset%25%29" awayState="1" awayMenu="1" autoRespond="1" system="1">
                    <Status medium="ASTRA" type="Away"/>
                </AwayMessage>
                <AwayMessage label="Set%20all%20Invisible" text="" awayState="1" awayMenu="1" autoRespond="0" system="1">
                    <Status medium="ASTRA" type="Invisible"/>
                </AwayMessage>
                <AwayMessage label="Set%20all%20Back" text="" awayState="0" awayMenu="1" autoRespond="0" system="1">
                    <Status medium="ASTRA" type="Online"/>
                </AwayMessage>
                <AwayMessage label="Set%20all%20Idle" text="Idle%20since%20%25time%25%20%28%25timeZoneOffset%25%29" awayState="1" awayMenu="0" autoRespond="1" system="1">
                    <Status medium="ASTRA" type="Away"/>
                </AwayMessage>
            </AwayGroup>
        </AwayList>
    </events>

变量$Path一次只能有一个目录,而不是它。

\\DFSROOT\DFSSHare\view\Profiles\User1\AppData\Roaming\Trillian\users\User1\Events.xml
\\DFSROOT\DFSSHare\view\Profiles\User2\AppData\Roaming\Trillian\users\User2\Events.xml
\\DFSROOT\DFSSHare\view\Profiles\User3\AppData\Roaming\Trillian\users\User3\Events.xml
\\DFSROOT\DFSSHare\view\Profiles\User4\AppData\Roaming\Trillian\users\User4\Events.xml
\\DFSROOT\DFSSHare\view\Profiles\User5\AppData\Roaming\Trillian\users\User5\Events.xml

2 个答案:

答案 0 :(得分:0)

问题在于,生成的$XMLPaths变量是字符串而不是数组。因此,您的ForEach表达式将变量$XMLPaths解释为一个元素的数组,其中一个元素是一个包含所有连接在一起的路径的字符串。

您可以随时输入$Variable来检查变量$Variable.GetType()的类型。例如,当我运行你的第一行代码时,这就是我所看到的:

PS > $XMLPaths.GetType()

IsPublic IsSerial Name    BaseType
-------- -------- ----    --------
True     True     String  System.Object

尝试用这个替换第一行:

#Remote Computers
$XMLPaths = (Get-ChildItem \\DFSRoot\DFS Share\view\Profiles\*\AppData\Roaming\Trillian\ -Recurse -Force | Where-Object {$_.Name -contains 'Events.xml'} | Select FullName).FullName

Select FullName子句之后,返回包含属性FullName的对象数组。因此,通过调用.FullName,它返回一个文件名数组。

您应该能够检查$XMLPaths是否为array类型:

PS > $XMLPaths.GetType()

IsPublic IsSerial Name      BaseType
-------- -------- ----      --------
True     True     Object[]  System.Array

答案 1 :(得分:0)

$XMLPaths.GetType().Name返回String。使用

$auxiliaryPath = "\\DFSRoot\DFS Share\view\Profiles\*\AppData\Roaming\Trillian"
$XMLPaths = (Get-ChildItem "$auxiliaryPath\Events.xml" -Recurse -Force).FullName