2017-05-20 66 views
1

我有一堆XML文件,我需要在節點文本中執行一些替換操作。我的代碼似乎無法更新<Notes>節點,因爲找不到它。我已經檢查了Notepad ++中的XML路徑,它看起來是正確的。替換不能在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>[email protected]</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 

我可能很明顯,但我不能馬上看到它。

回答

3

表達$xml.Organis...ailsRow.Notes給你的所有<ContactDetailsRow>節點<Notes>子節點(在您的示例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樣本只包含一個單獨的節點,所以它不會在那裏觸發這個問題。

+0

感謝@Ansgar Wiechers解釋爲什麼我的代碼是錯誤的 - 很好的理由爲什麼它錯了 – zoomzoomvince