1

I've got an XML file where a part of it are the GoodsItems element. I want to order the GoodsItem elements so that the ones having a subelement SupplementaryInformationLines.SupplementaryInformationLine with Code == "X002" and Text != "NLR" comes first. Subsequently all elements must be ordered by the GoodsItem.TaricCode element.

<GoodsItems>
  <GoodsItem>
    <GoodsDescription1>Some goods to be sorted last</GoodsDescription1>
    <TaricNumber>854129</TaricNumber>
    <SupplementaryInformationLines>
      <SupplementaryInformationLine>
        <Type>B.H</Type>
        <Code>X002</Code>
        <Text>NLR</Text>
      </SupplementaryInformationLine>
      <SupplementaryInformationLine>
        <Type>SU</Type>
        <Code></Code>
        <Text>Some text</Text>
      </SupplementaryInformationLine>
    </SupplementaryInformationLines>
  </GoodsItem>
  <GoodsItem>
    <GoodsDescription1>Some goods to be sorted first</GoodsDescription1>
    <TaricNumber>854129</TaricNumber>
    <SupplementaryInformationLines>
      <SupplementaryInformationLine>
        <Type>B.H</Type>
        <Code>X002</Code>
        <Text>SE_A_4324234</Text>
      </SupplementaryInformationLine>
      <SupplementaryInformationLine>
        <Type>SU</Type>
        <Code></Code>
        <Text>Some text</Text>
      </SupplementaryInformationLine>
    </SupplementaryInformationLines>
  </GoodsItem>
</GoodsItems>

I tested it and got it to work correctly with the first part of the ordering, then I added the TaricNumber ordering and changed from using .Value to get the string values of the elements in the where clause to casting to string instead since some files got a NullPointerException when using .Value. After these changes I cannot get it to work again. It only orders the GoodsItems by TaricNumber.

var query = from xeGoodsItem in xeCustClearance.Element(nsName + "GoodsItems").Elements(nsName + "GoodsItem")
    let sortValue1 = (
        from xeSuppInfo in xeGoodsItem.Element(nsName + "SupplementaryInformationLines").Elements(nsName + "SupplementaryInformationLine")
        where ((string)xeSuppInfo.Element("Code") == "X002" && (string)xeSuppInfo.Element("Text") != "NLR")
        select 1).FirstOrDefault()
    orderby sortValue1 descending, (string)xeGoodsItem.Element(nsName + "TaricNumber").Value ascending
    select xeGoodsItem;

I don't need to save the XML file with the ordering, I'm only doing the sort in-memory. Although using a ReplaceNode approach instead of a linq query could be a solution as well, I just need to get this thing to work.

Community
  • 1
  • 1
Trygve
  • 2,445
  • 1
  • 19
  • 23
  • The code looks good, and a minimal example with that xml and that query returns the `to be sorted first` element first, as required. – AakashM Sep 20 '11 at 10:32
  • Hmmm, that should give me a lead. I have simplified the xml since GoodsItems are part of a larger xml file. I didn't really test the simplified example myself. There's got to be something with the larger file that causes this behaviour. – Trygve Sep 20 '11 at 11:50
  • Duh, I found the error... I'd forgotten to add the nsName (namespace name) when referring to the "Code" and "Text" elements in the where clause. I probably had it correct in the initial test but when adding more code I left it out. Leaving out the nsName in other places gave me a NullReferenceException, but not those in the where clause. Thanks for leading me in the right direction... – Trygve Sep 20 '11 at 12:17

1 Answers1

2

Answered in my comment. It was a missing namespace name in front of the element name causing the ordering to not work as expected.

Trygve
  • 2,445
  • 1
  • 19
  • 23
  • This problem got me thinking and I believe it would have been a good idea to strip out namespace information from the xml nodes after loading the file but before doing any actual work on it. That way the test code and actual production code could work the same and I wouldn't have to have a lot of redundant namespace info to refer to the elements in code. http://social.msdn.microsoft.com/Forums/en-US/linqprojectgeneral/thread/bed57335-827a-4731-b6da-a7636ac29f21/ and http://stackoverflow.com/questions/1145659/ignore-namespaces-in-linq-to-xml. Any thoughts? – Trygve Sep 23 '11 at 09:11