0

I have the following xml file.(sample) .. I need to sort the 'invoice' nodes by the attribute 'InvcDate'. Is this even possible in Linq? Any help would be much appreciated.

I have been trying for some time however I don't have much experience with xml and and am a relative newcomer to programming, so I would be very grateful for any help at all.

<?xml version="1.0" encoding="utf-8"?>
<Server>
  <Name>AlignServer</Name>
  <Params>
<marketNo>MT</marketNo>
    <dateFrom>2015-01-06</dateFrom>
    <dateTo>2015-01-09</dateTo>
    <Sales>
      <invoices>
        <invoice>
          <header>
            <InvoiceNum>22947</InvoiceNum>
            <InvcDate>2015/01/07-110104</InvcDate>
          </header>
          <item>
            <SKU>6595456987453</SKU>
            <Qty>-1</Qty>
          </item>
        </invoice>
        <invoice>
          <header>
            <InvoiceNum>23056</InvoiceNum>
            <InvcDate>2015/01/08-020627</InvcDate>
          </header>
          <item>
            <SKU>9845256242255</SKU>
            <Qty>-1</Qty>
          </item>
        </invoice>
        <invoice>
          <header>
            <InvoiceNum>22899</InvoiceNum>
            <InvcDate>2015/01/06-094505</InvcDate>
          </header>
          <item>
            <SKU>5454256565452</SKU>
            <Qty>-1</Qty>
          </item>
          <item>
            <SKU>11111165454130</SKU>
            <Qty>4</Qty>
          </item>
        </invoice>
      </invoices>
    </Sales>
  </Params>
</Server>

I have tried

XElement root = XElement.Load("C:\\xmlsort\\test.xml");
XElement[] sortedTables = root.Elements("invoices").OrderBy(t =>   (Datetime)t.Element("invdate")).ToArray();
root.ReplaceAll(sortedTables);
root.Save("C:\\xmlsort\\test.xml");

What I have done so far - with suggestion from @ec8or and seems to work but still open to suggestions:

XElement root = XElement.Load("C:\\xmlsort\\test.xml");
var invoices = from p in root.Descendants("invoice")
                       orderby DateTime.ParseExact(p.Element("header").Element("InvcDate").Value, "yyyy/MM/dd-hhmmss", CultureInfo.InvariantCulture)
select p;
XElement[] sortedTables = invoices.ToArray();

root.ReplaceAll(sortedTables);
root.Save("C:\\xmlsort\\output.xml");
MaltaBd
  • 1
  • 2
  • 1
    have you tried anything? - Show us – Chuck Savage Feb 06 '15 at 20:37
  • XElement root = XElement.Load("C:\\xmlsort\\test.xml"); XElement[] sortedTables = root.Elements("invoices").OrderBy(t => (datetime)t.Element("invoice/InvcDate")).ToArray(); root.ReplaceAll(sortedTables); root.Save("C:\\xmlsort\\test.xml"); – MaltaBd Feb 07 '15 at 01:26

1 Answers1

1

Read you XML in a XElement:

XElement element = XElement.Load("doc.xml");

Query you XML data:

var invoices = from p in element.Descendants ("invoice")
               orderby DateTime.ParseExact(p.Element("header").Element("InvcDate").Value, "yyyy/MM/dd-hhmmss", CultureInfo.InvariantCulture)
               select p;

Print it to the console:

foreach (var invoice in invoices) {
    Console.WriteLine (invoice.ToString ());
}

EDIT Answer to your question in comments.

XDocument doc = XDocument.Load ("data.xml");

Select all parent node:

var baseElement = doc.XPathSelectElement ("/Server/Params/Sales/invoices");

sort the inner nodes:

var sortedElements = baseElement.Elements ()
    .OrderBy (e => (DateTime)e.XPathSelectElement("header/InvoiceNum"))
    .ToList (); 

replace the current content with the sortet content:

baseElement.ReplaceAll (sortedElements);
doc.Save ("out.xml");
devmb
  • 805
  • 6
  • 18
  • 1
    Why not use `XElement.Load("doc.xml")` instead of `XElement.Parse (File.ReadAllText("doc.xml"))`? – user4003407 Feb 07 '15 at 02:05
  • XElement root = XElement.Load("C:\\xmlsort\\test.xml"); var invoices = from p in root.Descendants("invoice") orderby DateTime.ParseExact(p.Element("header").Element("InvcDate").Value, "yyyy/MM/dd-hhmmss", CultureInfo.InvariantCulture) select p; XElement[] sortedTables = invoices.ToArray(); root.ReplaceAll(sortedTables); root.Save("C:\\xmlsort\\output.xml"); – MaltaBd Feb 07 '15 at 02:22
  • @PetSerAl You are right. – devmb Feb 08 '15 at 11:31
  • @MaltaBd Is that you solution or is that a question? If my answer helped you out, please mark it as answer. :) – devmb Feb 08 '15 at 11:33
  • @ec8or - I just realised something, the code I used removed previous nodes - "AlignServer MT 2015-01-06 2015-01-09 - How do I solve this? – MaltaBd Feb 10 '15 at 16:05