2

this is my xml file

<SW.Blocks.CompileUnit ID="3" CompositionName="CompileUnits">
<AttributeList>
    <NetworkSource>
        <FlgNet xmlns="http://www.siemens.com/automation/Openness/SW/NetworkSource/FlgNet/v2">
            <Parts>
                <Access Scope="GlobalVariable" UId="21">
                    <Symbol>
                        <Component Name="PlantConfigData" />
                        <Component Name="C001" />
                        <Component Name="command" />
                        <Component Name="conveyorGUID" />
                    </Symbol>
                </Access>
                <Access Scope="GlobalVariable" UId="22">
                    <Symbol>
                        <Component Name="PlantConfigData" />
                        <Component Name="C001" />
                    </Symbol>
                </Access>
                <Call UId="23">
                    <CallInfo Name="Conveyor Type C" BlockType="FB">
                        <Instance Scope="GlobalVariable" UId="24">
                            <Component Name="Conveyor Type C_DB" />
                        </Instance>
                        <Parameter Name="GUID" Section="Input" Type="String" />
                        <Parameter Name="Auto_Hand" Section="Input" Type="Bool" />
                        <Parameter Name="Notaus" Section="Input" Type="Bool" />
                        <Parameter Name="Input" Section="Input" Type="typeConveyorDrive" />
                        <Parameter Name="out1" Section="Output" Type="Bool" />
                    </CallInfo>
                </Call>
            </Parts>
            <Wires>
                <Wire UId="29">
                    <OpenCon UId="25" />
                    <NameCon UId="23" Name="en" />
                </Wire>
                <Wire UId="30">
                    <IdentCon UId="21" />
                    <NameCon UId="23" Name="GUID" />
                </Wire>
                <Wire UId="31">
                    <OpenCon UId="26" />
                    <NameCon UId="23" Name="Auto_Hand" />
                </Wire>
                <Wire UId="32">
                    <OpenCon UId="27" />
                    <NameCon UId="23" Name="Notaus" />
                </Wire>
                <Wire UId="33">
                    <IdentCon UId="22" />
                    <NameCon UId="23" Name="Input" />
                </Wire>
                <Wire UId="34">
                    <NameCon UId="23" Name="out1" />
                    <OpenCon UId="28" />
                </Wire>
            </Wires>
        </FlgNet>
    </NetworkSource>
    <ProgrammingLanguage>FBD</ProgrammingLanguage>
</AttributeList>
<ObjectList>
    <MultilingualText ID="4" CompositionName="Comment">
        <ObjectList>
            <MultilingualTextItem ID="5" CompositionName="Items">
                <AttributeList>
                    <Culture>de-DE</Culture>
                    <Text>Bausteinaufruf C001 GUID?</Text>
                </AttributeList>
            </MultilingualTextItem>
        </ObjectList>
    </MultilingualText>
    <MultilingualText ID="6" CompositionName="Title">
        <ObjectList>
            <MultilingualTextItem ID="7" CompositionName="Items">
                <AttributeList>
                    <Culture>de-DE</Culture>
                    <Text>C001</Text>
                </AttributeList>
            </MultilingualTextItem>
        </ObjectList>
    </MultilingualText>
</ObjectList>
</SW.Blocks.CompileUnit>

I want to filter all XElements with LINQ, which have the attribute name "ID" (called XName?!). I don't care about the value. I need to write my own values (like 1....10, for the next call 11...20) in all ID elements, because they have to be unique.

So there is my main xml, I will call the xml above, change values, and copy it in my main xml. Depends on my device count.

I saw a lot of examples for filtering after value, but not for the attribute name.

My code until know:

var id =
                from el in root.Descendants(nse_type + "SW.Blocks.CompileUnit")
                where // I need to filter?
                select el;

Maybe a better way is get all XElements with LINQ and filter in foreach() to change values with attribute name "ID"?

I'm a beginner, maybe its not that complicated. Thank you very much!

Jason Aller
  • 3,541
  • 28
  • 38
  • 38
BamBam24
  • 43
  • 3
  • So basically you want to be able to edit your XML string? One option is to 1) deserialize it into C# objects, then 2) change the objects and then 3) serialize the changed objects. – Rui Jarimba Oct 17 '18 at 14:50
  • Otherwise use Linq2XML, see https://stackoverflow.com/questions/1487653/update-xml-with-c-sharp-using-linq – Rui Jarimba Oct 17 '18 at 14:55

2 Answers2

2

Well, if you want to get all elements that have ID attribute, you can do the following:

var elements= from el in root.Descendants()
              where el.Attribute("ID") != null //This will check if the attribute exist or not              
              select el;

Now you can iterate over the result to update the attribute:

int i=0;
foreach (XElement e in elements)
{
  e.Attribute("ID").Value=(i++).ToString();
}
ocuenca
  • 38,548
  • 11
  • 89
  • 102
1

Like Rui Jarimba say, you should serialize and deserialize the xml, I think you should find your answer here : https://stackoverflow.com/a/14663848/5034209

After the deserialization, you can use Linq To object, use a for loop and change the ID.

At the end use serialization to recreate the xml.

The only behavior is that your xml will be different from the original one...

Also you could do it with Linq to XML :

Parse the XML

Loop over the Elements you want (using Linq query)

Change the Attribut Id (xml.SetAttributeValue("UId", 1))

Save the XML (xml.Save("[fileNameOrStream]"))

Dadv
  • 324
  • 2
  • 17