Objectmendername with Spaces

53 Views Asked by At

I have a CSV-List to replace Strings in an XML.

Now the CSV looks like:

First;Secound One; Third 
Name;Beschreibung Neu;Func1 
Number;handout her, func2

The Code is:

#Splatennamen auslesen
$CSVSpalten = $CSVData | Get-member -MemberType 'NoteProperty' | Select-Object -ExpandProperty 'Name'


# xml Objekt erstellen
$xml = New-Object XML
# xml laden
$xml.Load($OPN_in)

# Abfrage des ersten 'SW.Blocks.CompileUnit' Knotens
$Bsp_NW = $xml.SelectSingleNode("//SW.Blocks.CompileUnit")


# abbrechen wenn kein Knoten gefunden wurde.
if (!$Bsp_NW){
    throw "Error, 'SW.Blocks.CompileUnit' Node not found!"
    exit 1
}

$z=0
foreach($Zeile in $CSV_reseve)
{

    # erstelle eine Kopie des Knotens im Speicher
    $NEU_NW = $Bsp_NW.Clone()

    #Texte Ersetzen 
    foreach($spalte in $CSVSpalten)
        {
        #$NEU_NW.innerxml
        write-Host "ALt: $spalte  NEU: $Zeile.$spalte " 
        $NEU_NW.innerxml = $NEU_NW.innerxml -replace ("$spalte" -replace "'"),($Zeile."$spalte" -replace "'")

        #ID's verändern
        $z+=1
        $NEU_NW.innerxml = $NEU_NW.innerxml.Replace(' ID="',' ID="'+($z*10).ToString())
        #>
    }
    # id anpassen
    $NEU_NW.Id = (100*$z).ToString()

    # hänge den kopierten Knoten im selben Parent wie vom Original wieder ins XML ein
    $Bsp_NW.ParentNode.InsertAfter($NEU_NW,$Bsp_NW)
}

Problem is the row:

$NEU_NW.innerxml = $NEU_NW.innerxml -replace ("$spalte" -replace "'"),($Zeile."$spalte" -replace "'")

I think its because the Space in the Name of the 2. Colum and the Uses in -> $Zeile."$spalte" <-.

How can is Correct it?

2

There are 2 best solutions below

1
Chris Ryan On

Try replacing this line, as yours is a odd way to deal with the csv import.

$CSVData= import-csv $CSVFile -encoding -utf8 -delimiter ';'

If it still does not work, then try using this to modify the $spalte before the replace.

[string]$Spalte2 = $Spalte -replace "'"

$NEU_NW.innerxml = [string]$NEU_NW.innerxml -replace $spalte2,$Zeile.$Spalte2

See if removing the -replace sorts things.

1
TheRob87 On

XML-DATA

<?xml version="1.0" encoding="utf-8"?>
<Document>
  <Engineering version="V18" />
   <SW.Blocks.FB ID="0">
    <AttributeList>
      <Interface><Sections xmlns="http://www.siemens.com/automation/Openness/SW/Interface/v5">
   <Section Name="Static">
    <Member Name="C_SFC3600" Datatype="&quot;Control_SFC&quot;" Accessibility="Public">
      <AttributeList>
        <BooleanAttribute Name="ExternalAccessible" SystemDefined="true">true</BooleanAttribute>
      </AttributeList>
    </Member>
  </Section>
  <Section Name="Temp" />
  <Section Name="Constant" />
</Sections></Interface>

    </AttributeList>
    <ObjectList>
      <SW.Blocks.CompileUnit ID="3" CompositionName="CompileUnits">
        <AttributeList>
  <Parts>
    <Access Scope="LiteralConstant" UId="21">
      <Constant>
        <ConstantType>UInt</ConstantType>
        <ConstantValue>990</ConstantValue>
        <StringAttribute Name="Format" Informative="true">Dec_unsigned</StringAttribute>
      </Constant>
    </Access>
    <Access Scope="GlobalVariable" UId="22">
      <Symbol>
        <Component Name="SFC360" />
        <Component Name="_0" />
        <Component Name="Daten" />
        <Address Area="None" Type="UDT_SFC" BlockNumber="360" BitOffset="128" Informative="true" />
      </Symbol>
    </Access>
    <Access Scope="GlobalVariable" UId="23">
      <Symbol>
        <Component Name="SFC360" />
        <Component Name="_0" />
        <Component Name="Daten" />
        <Component Name="XBef" />
        <Component Name="Quittieren" />
        <Address Area="None" Type="Bool" BlockNumber="360" BitOffset="376" Informative="true" />
      </Symbol>
    </Access>
    <Access Scope="GlobalVariable" UId="24">
      <Symbol>
        <Component Name="SFC360" />
        <Component Name="_0" />
        <Component Name="Daten" />
        <Component Name="XBef" />
        <Component Name="Auto" />
        <Address Area="None" Type="Bool" BlockNumber="360" BitOffset="328" Informative="true" />
      </Symbol>
    </Access>
    <Access Scope="GlobalVariable" UId="25">
      <Symbol>
        <Component Name="SFC360" />
        <Component Name="_0" />
        <Component Name="Daten" />
        <Component Name="XBef" />
        <Component Name="Hand_mit_Trans" />
        <Address Area="None" Type="Bool" BlockNumber="360" BitOffset="360" Informative="true" />
      </Symbol>
    </Access>
    <Access Scope="GlobalVariable" UId="26">
      <Symbol>
        <Component Name="SFC360" />
        <Component Name="_0" />
        <Component Name="Daten" />
        <Component Name="XBef" />
        <Component Name="Hand_ohne_Trans" />
        <Address Area="None" Type="Bool" BlockNumber="360" BitOffset="368" Informative="true" />
      </Symbol>
    </Access>
    <Access Scope="GlobalVariable" UId="27">
      <Symbol>
        <Component Name="SFC360" />
        <Component Name="_0" />
        <Component Name="Daten" />
        <Component Name="XBef" />
        <Component Name="iHand" />
        <Address Area="None" Type="Bool" BlockNumber="360" BitOffset="320" Informative="true" />
      </Symbol>
    </Access>
    <Access Scope="GlobalVariable" UId="28">
      <Symbol>
        <Component Name="SFC360" />
        <Component Name="_0" />
        <Component Name="Daten" />
        <Component Name="Schrittnummer Soll" />
        <Address Area="None" Type="UInt" BlockNumber="360" BitOffset="176" Informative="true" />
      </Symbol>
    </Access>
    <Access Scope="GlobalVariable" UId="29">
      <Symbol>
        <Component Name="SFC360" />
        <Component Name="_0" />
        <Component Name="Daten" />
        <Component Name="XBef" />
        <Component Name="H_Nächster_Schritt" />
        <Address Area="None" Type="Bool" BlockNumber="360" BitOffset="384" Informative="true" />
      </Symbol>
    </Access>
    <Access Scope="GlobalVariable" UId="30">
      <Symbol>
        <Component Name="SFC360" />
        <Component Name="_0" />
        <Component Name="Daten" />
        <Component Name="Schrittnummer IST" />
        <Address Area="None" Type="UInt" BlockNumber="360" BitOffset="160" Informative="true" />
      </Symbol>
    </Access>
    <Access Scope="GlobalVariable" UId="31">
      <Symbol>
        <Component Name="SFC360" />
        <Component Name="_0" />
        <Component Name="Daten" />
        <Component Name="XSta" />
        <Component Name="Transition_OK" />
        <Address Area="None" Type="Bool" BlockNumber="360" BitOffset="312" Informative="true" />
      </Symbol>
    </Access>
    <Access Scope="GlobalVariable" UId="32">
      <Symbol>
        <Component Name="SFC360" />
        <Component Name="_0" />
        <Component Name="Daten" />
        <Component Name="XSta" />
        <Component Name="Störung" />
        <Address Area="None" Type="Bool" BlockNumber="360" BitOffset="248" Informative="true" />
      </Symbol>
    </Access>
    <Access Scope="GlobalVariable" UId="33">
      <Symbol>
        <Component Name="SFC360" />
        <Component Name="_0" />
        <Component Name="Daten" />
        <Component Name="XSta" />
        <Component Name="Auto(0=Hand; 1=Auto))" />
        <Address Area="None" Type="Bool" BlockNumber="360" BitOffset="208" Informative="true" />
      </Symbol>
    </Access>
    <Access Scope="GlobalVariable" UId="34">
      <Symbol>
        <Component Name="SFC360" />
        <Component Name="_0" />
        <Component Name="Daten" />
        <Component Name="XSta" />
        <Component Name="Hand_mit_Trans" />
        <Address Area="None" Type="Bool" BlockNumber="360" BitOffset="216" Informative="true" />
      </Symbol>
    </Access>
    <Access Scope="GlobalVariable" UId="35">
      <Symbol>
        <Component Name="SFC360" />
        <Component Name="_0" />
        <Component Name="Daten" />
        <Component Name="XSta" />
        <Component Name="Hand_ohne_Trans" />
        <Address Area="None" Type="Bool" BlockNumber="360" BitOffset="224" Informative="true" />
      </Symbol>
    </Access>
    <Access Scope="GlobalVariable" UId="36">
      <Symbol>
        <Component Name="SFC360" />
        <Component Name="_0" />
        <Component Name="Daten" />
        <Component Name="XSta" />
        <Component Name="iHand" />
        <Address Area="None" Type="Bool" BlockNumber="360" BitOffset="232" Informative="true" />
      </Symbol>
    </Access>
    <Call UId="37">
      <CallInfo Name="Control_SFC" BlockType="FB">
        <IntegerAttribute Name="BlockNumber" Informative="true">997</IntegerAttribute>
        <DateAttribute Name="ParameterModifiedTS" Informative="true">2024-01-16T13:59:43</DateAttribute>
        <Instance Scope="LocalVariable" UId="38">
          <Component Name="C_SFC3600" />
        </Instance>
        <Parameter Name="Abbruch_Start_Schritt" Section="Input" Type="UInt">
          <StringAttribute Name="InterfaceFlags" Informative="true">S7_Visible</StringAttribute>
        </Parameter>
        <Parameter Name="Daten" Section="InOut" Type="&quot;UDT_SFC&quot;">
          <StringAttribute Name="InterfaceFlags" Informative="true">S7_Visible</StringAttribute>
        </Parameter>
      </CallInfo>
    </Call>
 </Parts>
</FlgNet></NetworkSource>
          <ProgrammingLanguage>FBD</ProgrammingLanguage>
          <MultilingualText ID="6" CompositionName="Title">
            <ObjectList>
              <MultilingualTextItem ID="7" CompositionName="Items">
                <AttributeList>
                  <Culture>de-DE</Culture>
                  <Text>SFC3600 - Produktion Linie1</Text>
                </AttributeList>
              </MultilingualTextItem>
            </ObjectList>
          </MultilingualText>
        </ObjectList>
      </SW.Blocks.CompileUnit>
      <MultilingualText ID="D" CompositionName="Title">
        <ObjectList>
          <MultilingualTextItem ID="E" CompositionName="Items">
            <AttributeList>
              <Culture>de-DE</Culture>
              <Text />
            </AttributeList>
          </MultilingualTextItem>
        </ObjectList>
      </MultilingualText>
    </ObjectList>
  </SW.Blocks.FB>
</Document>

CSV:

3600;SFC3600 - Produktion Linie1;SFC360._0.Daten
3601;SFC3601 - CIP Linie1;SFC360._1.Daten
3602;SFC3602 - SIP Linie1;SFC360._2.Daten

I'd like to copy the Node [ <SW.Blocks.CompileUnit ID="3" CompositionName="CompileUnits"> ] and change the text "SFC3600 - Produktion Linie1" to "CIP Linie1" (and "SFC3602 - SIP Linie1")

The full Powershell:

Set-Location -path C:\OPN
#Powersehll funktionen importieren
. .\scripte\Functions.ps1
#Array Objektname
$CSVFile = (GetFile -Info "CSV-Datei" -DataType "csv")[1]
$CSVData= GetCsvAsObject($CSVFile)
$OPN_in =(GetFile -Info "FC/FB-FILE")[1]
$CSVName = (Get-Item $CSVFile).BaseName
$OPN_Out="C:\OPN\imp\$CSVName.xml"
$CSVData
## CSV sortierung umdrehen
$CSV_reseve=$CSVData.Clone()
for ($i=1; $i -lt $CSVData.Length; $i++) {
$CSV_reseve[$i]= $CSVData[$CSVData.Length-$i]

}

cls

#Splatennamen auslesen
$CSVSpalten = $CSVData | Get-member -MemberType 'NoteProperty' | Select-Object -ExpandProperty 'Name'


# xml Objekt erstellen
$xml = New-Object XML
# xml laden
$xml.Load($OPN_in)

# Abfrage des ersten 'SW.Blocks.CompileUnit' Knotens
$Bsp_NW = $xml.SelectSingleNode("//SW.Blocks.CompileUnit")


# abbrechen wenn kein Knoten gefunden wurde.
if (!$Bsp_NW){
    throw "Error, 'SW.Blocks.CompileUnit' Node not found!"
    exit 1
}

$z=0
foreach($Zeile in $CSV_reseve)
{

    # erstelle eine Kopie des Knotens im Speicher
    $NEU_NW = $Bsp_NW.Clone()

    #Texte Ersetzen 
    foreach($spalte in $CSVSpalten)
        {
        #$NEU_NW.innerxml
        write-Host "ALt: $spalte  NEU: $Zeile.$spalte " 
        $NEU_NW.innerxml = $NEU_NW.innerxml -replace ("$spalte" -replace "'"),($Zeile."$spalte" -replace "'")

        #ID's verändern
        $z+=1
        $NEU_NW.innerxml = $NEU_NW.innerxml.Replace(' ID="',' ID="'+($z*10).ToString())
        #>
    }
    # id anpassen
    $NEU_NW.Id = (100*$z).ToString()

    # hänge den kopierten Knoten im selben Parent wie vom Original wieder ins XML ein
    $Bsp_NW.ParentNode.InsertAfter($NEU_NW,$Bsp_NW)
}

#Basisdatenändern
$xml.Document.'SW.Blocks.FB'.AttributeList.Name =[STRING]$CSVName
$xml.Document.'SW.Blocks.FB'.AttributeList.Number = [String]($xml.Document.'SW.Blocks.FB'.AttributeList.Number+'00')


# speichere das geänderte xml unter neuem Namen
$xml.Save($OPN_Out)
#>

The Function Powershell:

function GetCsvAsObject($CSVPath){
    
if ($CSVPath)
    {

    (Get-Content $CSVPath)|
    ForEach-Object{$_ -replace ';',","}| # simikolon ersetzen
    ForEach-Object{$_ -replace '´t',","}| #Tab ersetzen
    Set-Content $CSVPath -Encoding UTF8
    #Get-Content $CSVPath 
    #Set-Content $CSVPath $CSVText

    return Import-Csv -Path $CSVPath -Delimiter ","
    }


}

function GetFile{
    Param( $path = [STRING]"C:\OPN",
           $Info = [STRING]"XML-FILE",
           $DataType = [STRING]"xml" 

      )

        [void] [Reflection.Assembly]::LoadWithPartialName( 'System.Windows.Forms' )

        $d = New-Object Windows.Forms.OpenFileDialog


        $d.InitialDirectory = "C:\OPN"
        $d.Filter = "$Info (*.$DataType)|*.$DataType|All files (*.*)|*.*";
        $d.ShowHelp = $true
        $d.ShowDialog((New-Object System.Windows.Forms.Form -Property @{TopMost = $true; TopLevel = $true}))

        return $d.FileName



        }