Canacourse
Canacourse

Reputation: 1865

Linq duplicate elements when iterating over XML

 <?xml version='1.0' encoding='utf-8' standalone='yes'?>
    <stock-items>
      <stock-item>
        <name>Loader 34</name>
        <sku>45GH6</sku>
        <vendor>HITINANY</vendor>
        <useage>Lifter 45 models B to C</useage>
        <typeid>01</typeid>
        <version>01</version>
        <reference>33</reference>
        <comments>EOL item. No Re-order</comments>
        <traits>
          <header>56765</header>
          <site>H4</site>
          <site>A6</site>
          <site>V1</site>
        </traits>  
        <type-validators>
          <actions>
            <endurance-tester>bake/shake</endurance-tester>
          </actions>
          <rules>
            <results-file>Test-Results.txt</results-file>
            <file-must-contain file-name="Test-Results.xml">
              <search>
                <term>[<![CDATA[<"TEST TYPES 23 & 49 PASSED"/>]]></term>
                <search-type>exactMatch</search-type>
              </search>
            </file-must-contain>
          </rules>
        </type-validators>
      </stock-item>
    </stock-items>

Im trying to get the rules fragment from the xml above into a string so it can be added to a database. Currently the search element and its contents are added twice. I know why this is happing but cant figure out how to prevent it.

Heres my code

    var Rules = from rules in Type.Descendants("rules")
                                       select rules.Descendants(); 

              StringBuilder RulesString = new StringBuilder();

              foreach (var rule in Rules)
                    {   
                      foreach (var item in rule)
                      {      
                              RulesString.AppendLine(item.ToString());
                      }
                    }

 Console.WriteLine(RulesString);

Finally any elements in rules are optional and some of these elements may or may not contain other child elements up to 4 or 5 levels deep. TIA

UPDATE: To try and make it clearer what im trying to achieve.

From the xml above I should end up with a string containing everthing in the rules element, exactly like this:

<results-file>Test-Results.txt</results-file>
                <file-must-contain file-name="Test-Results.xml">
                  <search>
                    <term>[<![CDATA[<"TEST TYPES 23 & 49 PASSED"/>]]></term>
                    <search-type>exactMatch</search-type>
                  </search>
                </file-must-contain>

Upvotes: 2

Views: 281

Answers (2)

Jason Meckley
Jason Meckley

Reputation: 7591

if you want to prevent duplicates than you will need to use Distinct() or GroupBy() after parsing the xml and before building the string.

I'm still not fully understanding exactly what the output should be, so I can't provide a clear solution on what exactly to use, or how, in terms of locating duplicates. If you can refine the original post that would help.

  1. we need the structure of the xml as it would appear in your scenario. nesting and all.
  2. we need an example of the final string. saving it to a db doesn't really matter for this post so you only need to briefly mention that once, if at all.

Upvotes: 0

AakashM
AakashM

Reputation: 63338

Objective is to extract the entire contents of the rules element as is while taking account that the rules element may or may not contains child elements several levels deep

If you just want the entirety of the rules element as a string (rather than caring about its contents as xml), you don't need to dig into its contents, you just need to get the element as an XNode and then call ToString() on it :

The following example uses this method to retrieve indented XML.

XElement xmlTree = new XElement("Root",
    new XElement("Child1", 1)
);
Console.WriteLine(xmlTree);

This example produces the following output:

<Root>
  <Child1>1</Child1>
</Root>

Upvotes: 3

Related Questions