替换不在XML节点

时间:2017-05-20 12:56:31

标签: xml powershell replace

我有一堆XML文件,我需要在节点文本中做一些替换操作。我的代码似乎无法更新<Notes>节点,因为找不到它。我已经在Notepad ++中检查了XML路径,看起来是正确的。

这是我用来测试的示例XML文件。

<?xml version="1.0" encoding="UTF-8"?>
<OrganisationUnits>
  <OrganisationUnitsRow num="21">
    <OrganisationId>ORG1</OrganisationId>
    <OrganisationName>ORG 1 TEST</OrganisationName>
    <Addresses>
      <AddressesRow num="1">
        <AddressId>E41002</AddressId>
        <MainAddress>Y</MainAddress>
      </AddressesRow>
    </Addresses>
    <ContactDetails>
      <ContactDetailsRow num="1">
        <ContactId>E6366</ContactId>
        <ContactCode>OFFICE</ContactCode>
        <Main>N</Main>
        <Notes>start date 11/03/1994</Notes>
      </ContactDetailsRow>
      <ContactDetailsRow num="2">
        <ContactId>E6367</ContactId>
        <ContactCode>WORK</ContactCode>
        <Main>N</Main>
        <Notes>start date 11/03/1995</Notes>
      </ContactDetailsRow>
      <ContactDetailsRow num="3">
        <ContactId>E6368</ContactId>
        <ContactCode>HOME</ContactCode>
        <Main>Y</Main>
        <Notes>start date - after 11/03/1995</Notes>
      </ContactDetailsRow>
      <ContactDetailsRow num="4">
        <ContactId>E6369</ContactId>
        <ContactCode>EMAIL</ContactCode>
        <ContactCodeDesc>Email Address</ContactCodeDesc>
        <ContactValue>info@yahoo.com</ContactValue>
        <StartDate>2000-03-11</StartDate>
        <Main>N</Main>
        <Notes>more test notes</Notes>
      </ContactDetailsRow>
    </ContactDetails>
    <Sector>P</Sector>
    <SectorDesc>Private</SectorDesc>
  </OrganisationUnitsRow>
</OrganisationUnits>

这是我的剧本。

#----- get source xml file(e) from the folder below ---#
$path = "C:\Dump\TEST"
$Files = Get-Childitem -path $path -File -include test_file_1.xml -name

# For every file in the folder specified perform a series of actions below
foreach ($File in $Files)
{
    Write-Host "=== FILE is $File ===" -ForegroundColor "White"
    $xml = [xml](Get-Content $path\$File)

    ## SectorDesc
    # check to ensure that we have got a SectorDesc row
    foreach ($OrganisationUnitsRow in $xml.OrganisationUnits.OrganisationUnitsRow)
    {
        if ($OrganisationUnitsRow.Item('SectorDesc'))
        {
            $xml.OrganisationUnits.OrganisationUnitsRow.SectorDesc = $xml.OrganisationUnits.OrganisationUnitsRow.SectorDesc.Replace("`b" , "\b")             #backspace
            $xml.OrganisationUnits.OrganisationUnitsRow.SectorDesc = $xml.OrganisationUnits.OrganisationUnitsRow.SectorDesc.Replace("`f" , "\f")             #form feed
        }
    }

    ## Notes
    # check to ensure that we have got a Notes row
    foreach ($ContactDetailsRow in $xml.OrganisationUnits.OrganisationUnitsRow.ContactDetails.ContactDetailsRow)
    {
        if ($ContactDetailsRow.Item('Notes'))
        {
            Write-Host "$ContactDetailsRow.Notes"
            $xml.OrganisationUnits.OrganisationUnitsRow.ContactDetails.ContactDetailsRow.Notes = $xml.OrganisationUnits.OrganisationUnitsRow.ContactDetails.ContactDetailsRow.Notes.Replace("\" , "\\")                #back slash
            $xml.OrganisationUnits.OrganisationUnitsRow.ContactDetails.ContactDetailsRow.Notes = $xml.OrganisationUnits.OrganisationUnitsRow.ContactDetails.ContactDetailsRow.Notes.Replace("`b" , "\b")             #backspace
        }

    }

    $xml.Save("$path\$File")
}

当脚本运行时,它会抛出错误。

Property 'Notes' cannot be found on this object; make sure it exists and is
settable.
At C:\Dump\test10.ps1:33 char:8
+                 $xml.OrganisationUnits.OrganisationUnitsRow.ContactDetails.ContactDetails ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : PropertyAssignmentException

Property 'Notes' cannot be found on this object; make sure it exists and is
settable.
At C:\Dump\test10.ps1:34 char:8
+                 $xml.OrganisationUnits.OrganisationUnitsRow.ContactDetails.ContactDetails ...
+    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : PropertyAssignmentException

我可能很明显,但我不能马上看到它。

1 个答案:

答案 0 :(得分:3)

表达式$xml.Organis...ailsRow.Notes为您提供所有 <Notes>个节点的<ContactDetailsRow>子节点(在您的示例4中)。请改用循环变量(并且可以菊花链式Replace()次调用):

foreach ($ContactDetailsRow in $xml.OrganisationUnits.OrganisationUnitsRow.ContactDetails.ContactDetailsRow)
{
    if ($ContactDetailsRow.Item('Notes'))
    {           
        Write-Host "$ContactDetailsRow.Notes"
        $ContactDetailsRow.Notes = $ContactDetailsRow.Notes.Replace("\", "\\").Replace("`b", "\b")
    }
}

更好的是,直接选择带有XPath表达式的<Notes>子节点:

$xml.SelectNodes('//ContactDetailsRow/Notes') | ForEach-Object {
    $_.'#text' = $_.'#text'.Replace("\", "\\").Replace("`b", "\b")
}

你的代码没有为你的第一个嵌套循环(你犯了同样的错误)抛出相同的错误的原因是你的XML示例只包含一个<SectorDesc>节点,所以它不会#&# 39;在那里引发问题。