-1

I have an XML file which has many children:

<Docs>
    <Doc>
        <DocType>x</DocType>
        <DocNumber>xxx</DocNumber>
        <DocNumberSeries>xx</DocNumberSeries>
        <DocDate>xxxx-xx-xx</DocDate>
        <DocCause>
            <Id>xx</Id>
            <Code/>
            <Name>xx</Name>
        </DocCause>
        <Anag>
            <Name>NameCompany</Name>
            <Address>xx</Address>
            <ZipCode>xx</ZipCode>
            <City>xx</City>
            <Province>xx</Province>
            <CountryCode>xx</CountryCode>
            <PhoneNumber>xx</PhoneNumber>
            <CellularNumber/>
            <FaxNumber>xx</FaxNumber>
            <EmailAddress>xx</EmailAddress>
            <VatNumber>xx</VatNumber>
            <PersonalID>xx</PersonalID>
        </Anag>
        <DestinationAddress>
            <Name>xxL</Name>
            <Address>xx</Address>
            <ZipCode>xx</ZipCode>
            <City>xx</City>
            <Province>xx</Province>
            <CountryCode>xx</CountryCode>
            <PhoneNumber>xx</PhoneNumber>
            <FaxNumber>xx</FaxNumber>
        </DestinationAddress>
        <Payment>
            <Code/>
            <Name>xx</Name>
        </Payment>
        <DocRows>
            <DocRow>
                <RowType>1</RowType>
                <Product>
                    <Code>LSML1710</Code>
                </Product>
                <Description></Description>
                <Quantity></Quantity>
                <Price></Price>
                <Tax>
                    <Tax>
                        <Id>xx</Id>
                        <Code/>
                        <Name>xx</Name>
                        <PercentAmount>xx</PercentAmount>
                        <IndPercentAmount>x</IndPercentAmount>
                        <FixedAmount>x</FixedAmount>
                    </Tax>
                </Tax>
            </DocRow>
        </DocRows>
    ...
    </Doc>

For example, one of the thing I want to do is to get the data inside tag Doc and then Anag.

At the moment I have these classes:

public class Anag
{
    public string RagioneSociale { get; set; }
    public string Indirizzo { get; set; }
    public string CAP { get; set; }
    public string Citta { get; set; }
    public string Provincia { get; set; }
    public string CodiceNazione { get; set; }
    public string Telefono { get; set; }
    public string Cellulare { get; set; }
    public string Email { get; set; }
}

public class Doc
{
    public string DocNumber { get; set; }
    public Anag Anags { get; set; }
}
List<Doc> results = contentFile.Descendants("Doc").Select(doc => new Doc // var results = contentFile.Descendants("Doc").SelectMany(doc => doc.Descendants(doc.Name.Namespace + "Anag").Select(anag => new
{
    DocNumber = (string)doc.Element(doc.Name.Namespace + "DocNumber"),
    Anags = doc.Descendants(doc.Name.Namespace + "Anag").Select(anag => new Anag
    {
        RagioneSociale = (string)anag.Element(anag.Name.Namespace + "Name"),
        Indirizzo = (string)anag.Element(anag.Name.Namespace + "Address"),
        CAP = (string)anag.Element(anag.Name.Namespace + "ZipCode"),
        Provincia = (string)anag.Element(anag.Name.Namespace + "Province"),
        Telefono = (string)anag.Element(anag.Name.Namespace + "PhoneNumber"),
        Cellulare = (string)anag.Element(anag.Name.Namespace + "CellularNumber"),
        Email = (string)anag.Element(anag.Name.Namespace + "EmailAddress"),
        Citta = (string)anag.Element(anag.Name.Namespace + "City")
    }),
}).ToList();

This last code gives an error:

Cannot implicitly convert type system.collections.generic.IEnumerable<nameProject.Classes.Anag> in <NameProject.Classes.Anag>.

The final result I want is a List with the data and children of this XML:

List:

+ Doc=> 
 {DocNumber}
+ Anag => { Address .. , Name.. .. )   (not a list ! )
+ DestinationAddress => { Address.... Name..)

so that I can convert to a file .csv only .

GSerg
  • 76,472
  • 17
  • 159
  • 346
staff614
  • 71
  • 8
  • 1
    _"so that I can convert to a file .csv only "_ Use [XSLT](https://www.w3.org/standards/xml/transformation) instead. – Fildor Oct 28 '19 at 10:06
  • ^-- You can [perform the transformation from C#](https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/linq/using-xslt-to-transform-an-xml-tree), but the transformation itself would be defined in a transformation file using a language specifically designed for that task. It will be much more convenient and give you the freedom to change (adapt or fix) it without having to recompile your C# code. (Not an answer, because I am suggesting to use something completely different.) – Fildor Oct 28 '19 at 10:14
  • Get inspired here: [XML to CSV Using XSLT](https://stackoverflow.com/q/365312/982149) – Fildor Oct 28 '19 at 10:22

2 Answers2

0

Just try using the feature "Paste Special" to generate the classes for parsing. You will 100% not get an exception.

  1. Crtl + A on the whole xml, copy to clipboard
  2. Then create a new class in your project Click "Edit" -> "Paste Special" -> "Paste XML as classes"
  3. Change the parsing to use type of the "RootNode" in the pasted class
  4. Build and try it out.
Kristóf Tóth
  • 791
  • 4
  • 19
  • I am using a WPF project, not .NET, i think it works just with .net framework ? – staff614 Oct 28 '19 at 10:20
  • 1
    What do you mean not .NET? "Windows Presentation Foundation (WPF) is a graphical subsystem (similar to WinForms) originally developed by Microsoft for rendering user interfaces in Windows-based applications. WPF, previously known as "Avalon", was initially released as part of .NET Framework 3.0 in 2006. WPF uses DirectX and attempts to provide a consistent programming model for building applications. It separates the user interface from business logic, and resembles similar XML-oriented object models, such as those implemented in XUL and SVG." – Kristóf Tóth Oct 28 '19 at 10:21
  • Ok didn't know ty – staff614 Oct 28 '19 at 10:26
  • I did it, classes are generated, but remain the problem of how putting data from Xml to a list, how to assign data with LINQ to classes and attributes – staff614 Oct 28 '19 at 10:32
  • @staff614 I really recommend you don't bother with this and dive into xslt. It will be 1 or 2 hours of learning, then some try&error, but it will save you days in development. – Fildor Oct 28 '19 at 10:34
  • 1
    @staff614 update your question with some sample code when you have a successful parse – Kristóf Tóth Oct 28 '19 at 10:37
0

Since you already went through the trouble of creating the classes, why not let the deserializer do the job for you?

Here's how:

XmlSerializer serializer = new XmlSerializer(typeof(Root));
using (var reader = new StreamReader(xmlFilePath))
{
    List<Doc> docs = ((Root)serializer.Deserialize(reader)).Docs;
}

Now, you just have to add some tags into your class properties so that they match the xml names.

[Serializable, XmlRoot("Docs")]
public class Root
{
    [XmlElement("Doc")]
    public List<Doc> Docs { get; set; }
}

public class Doc
{
    public string DocNumber { get; set; }

    [XmlElement("Anag")]
    public Anag Anags { get; set; }
}

public class Anag
{
    [XmlElement("Name")]
    public string RagioneSociale { get; set; }

    [XmlElement("Address")]
    public string Indirizzo { get; set; }

    [XmlElement("ZipCode")]
    public string CAP { get; set; }

    [XmlElement("City")]
    public string Citta { get; set; }

    [XmlElement("Province")]
    public string Provincia { get; set; }

    [XmlElement("CountryCode")]
    public string CodiceNazione { get; set; }

    [XmlElement("PhoneNumber")]
    public string Telefono { get; set; }

    [XmlElement("CellularNumber")]
    public string Cellulare { get; set; }

    [XmlElement("EmailAddress")]
    public string Email { get; set; }
}
Innat3
  • 3,561
  • 2
  • 11
  • 29