views:

167

answers:

1

Hi I want to copy an xml file and insert in a specific element locaiton some more elements; What is the best and easiest way doing this. I can use xmlReader read elements and write one by one referring to each and every type- I had some issues with this but besides this seems to me too mush work that can be done somehow better. in the example below I have the xml as a default definition need to create a new xml in same format with inserting new values to sheet1 - but after existing rows, and do the same for sheet2.

<book>
   <Sheet ss:name="Sheet1">
      <Table >
      <Row >
        <Cell/>
        <Cell>
             Title Name      
        </Cell>
        <Cell >
             Title Description
         </Cell>
      </Row>
   </Sheet>
<a/>
<b/>
  <Sheet ss:name="Sheet2">
      <Table >
      <Row >
        <Cell/>
        <Cell>
             Title Name      
        </Cell>
        <Cell >
             Title Description
         </Cell>
      </Row>
   </Sheet>
</book>
+7  A: 

The simplest way in my view would be to load the whole document using LINQ to XML, modify it, then save it out again. That's likely to be easier than using XmlReader, which can get somewhat hairy in my experience.

However, that does involve loading it all into memory - which could be an issue if the documents are huge. Is that likely to be a problem?

EDIT: Here's a short example in LINQ to XML (untested):

XDocument doc = XDocument.Load("test.xml");
XNamespace ss = "http://url/for/ss";
Sheet sheet1 = doc.Descendants("Sheet")
                  .Where(x => (string) x.Attribute(ss + "name") == "Sheet1");
XElement lastRow = sheet1.Elements("Row").LastOrDefault();
// Note: if there aren't any rows, lastRow will be null here. Handle accordingly
lastRow.AddAfterSelf(new XElement("Foo", "Extra value"));

An alternative to the last part, if you just want the new content after all the old content of the sheet:

sheet1.Add(new XElement("Foo", "Extra value"));
Jon Skeet
Seems so, The original xmlFormat file is not that huge, while the final results might contain a few MB. Have any links/example of how to do this using linq. I need to get all data untill found element (shhet in the example) copy it to new xml, insert new data, and copy all data after desired element. Thanks for your help!!! Plus- what si the comparison of advantages/disadvantages between xmlReader or linq to xml in this case
You don't need to do any copying if you're reading the whole thing into memory: just modify the tree appropriately, then save it out afterwards. The benefit of LINQ to XML over XmlReader is that the code will be a lot simpler. The downside is that you *will* have all the data in memory. A few MB shouldn't be a problem at all. I'll write a little example of what you might do.
Jon Skeet
Thanks, appreciate it. From what size of file should I be concerned?
@user271077: It really depends on details of your situation. Basically, can you afford to have it all in memory? You'll have to experiment to see what size of file takes up how much memory.
Jon Skeet
Thanks,A comment: when getting a namespcae it should be done by using XNamespace ss = XNameSpcae.Get("http://url/for/ss"); it didn't work for me whan asigning directly
@user271077: It should have done - that's the way I've *always* done it. What happened when you tried?
Jon Skeet
A simpler way, certainly is to use an XSLT transformation! Never use such absolute statements -- most of the time they would be wrong! :)
Dimitre Novatchev
@Dimitre: For me, writing an XSLT transformation would definitely take longer than using LINQ to XML :) (Also bear in mind that we don't know where the extra data comes from.)
Jon Skeet
So, it would be correct if you replace the phrase *the simplest way* with something more correct. Or, would you like me to provide the XSLT transformation so that it would be obvious which solution is simpler? :)
Dimitre Novatchev