Avatar billede Greenland Nybegynder
16. november 2012 - 15:46 Der er 11 kommentarer og
1 løsning

linq - select af flere columns

Hej,

Jeg har selectet et column/element i xml vha linq i c#:

lst.Items.Clear();
var q = from c in XDocument.Load(@"C:\temp\product.xml").Descendants("Product")
from view in c.Element("member").Elements("ProductView")
//where (int)view.Element("ViewId") == 44

from fieldId in view.Elements("myfield")
//from assetText in view.Elements("AssetText")
select fieldId.Element("Text");


foreach (XElement item in q)
{
lst.Items.Add(item.Value);
}

det giver mig to tekster for id 44 og en for 45 so far so good.
Men hvordan får jeg AssetText med også?

Jeg ønsker at selecte mere end et felt under ProductView, og jeg tænkte noget med:
..
from fieldId in view.Elements("myfield")
from assetText in view.Elements("AssetText")
og så noget med:
select assetText.Element("Text"),select fieldId.Element("Text");
... men det virker desværre ikke:-(

xml´en ser således ud:

<Product>
  <member>
  <ProductView>
    <ViewId>44</ViewId>
    <AssetText>
      <Text>my first Asset Text</Text>
    </AssetText>
    <myfield>
      <Text>first myfield belongs to id 44</Text>
    </myfield>
    <AssetText>
      <Text>my second Asset Text</Text>
    </AssetText>
    <myfield>
      <Text>next myfield belongs to id 44</Text>
    </myfield>
  </ProductView>
  <ProductView>
    <ViewId>45</ViewId>
    <AssetText>
      <Text>my third Asset Text</Text>
    </AssetText>
    <myfield>
      <Text>first myfield belongs to id 45</Text>
    </myfield>
  </ProductView>
  </member>
</Product>


På forhånd takk!

Greenland
Avatar billede arne_v Ekspert
16. november 2012 - 16:08 #1
hvis du har en klasse X med 2 properties AT og FI saa:


select new X { AT=assetText.Element("Text"), FI=fieldId.Element("Text") };
Avatar billede Greenland Nybegynder
16. november 2012 - 16:42 #2
hvor får du det dog fra... arne :-)

koden ser nu således ud:

class X
            {
                string at = "";
                  public string AT
                    {
                        set {at = value; }
                        get {return at; }
                    }

                  string fi = "";
                  public string FI
                  {
                      set { fi = value; }
                      get { return fi; }
                  }

            }
var q = from c in XDocument.Load(@"C:\temp\product.xml").Descendants("Product")
  from view in c.Element("member").Elements("ProductView")
  //where (int)view.Element("ViewId") == 44
  from fieldId in view.Elements("myfield")
  from assetText in view.Elements("AssetText")
  select new X { AT = assetText.Element("Text").ToString(), FI = fieldId.Element("Text").ToString() };

  foreach (X item in q)
  {
    lst.Items.Add(item.AT + " " +  item.FI);
  }

.. dog får jeg ligesom innerXml med a.la:
<Text>my first Asset Text</Text> <Text>first myfield belongs to id 44</Text>
osv..

er det muligt at kun få værdierne?
Avatar billede Greenland Nybegynder
16. november 2012 - 16:44 #3
hvor får du det dog fra... arne :-)

koden ser nu således ud:

class X
            {
                string at = "";
                  public string AT
                    {
                        set {at = value; }
                        get {return at; }
                    }

                  string fi = "";
                  public string FI
                  {
                      set { fi = value; }
                      get { return fi; }
                  }

            }
var q = from c in XDocument.Load(@"C:\temp\product.xml").Descendants("Product")
  from view in c.Element("member").Elements("ProductView")
  //where (int)view.Element("ViewId") == 44
  from fieldId in view.Elements("myfield")
  from assetText in view.Elements("AssetText")
  select new X { AT = assetText.Element("Text").ToString(), FI = fieldId.Element("Text").ToString() };

  foreach (X item in q)
  {
    lst.Items.Add(item.AT + " " +  item.FI);
  }

.. dog får jeg ligesom innerXml med a.la:
<Text>my first Asset Text</Text> <Text>first myfield belongs to id 44</Text>
osv..

er det muligt at kun få værdierne?
Avatar billede arne_v Ekspert
16. november 2012 - 16:57 #4
maaske

select new X { AT = assetText.Element("Text").Value, FI = fieldId.Element("Text").Value }
Avatar billede arne_v Ekspert
17. november 2012 - 03:10 #5
Komplet forslag:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;

namespace E
{
    public class Data
    {
        public string AssetText { get; set; }
        public string MyField { get; set; }
    }
    public class Program
    {
        public static void Main(string[] args)
        {
            string xmlstr = @"<Product>
  <member>
  <ProductView>
    <ViewId>44</ViewId>
    <AssetText>
      <Text>my first Asset Text</Text>
    </AssetText>
    <myfield>
      <Text>first myfield belongs to id 44</Text>
    </myfield>
    <AssetText>
      <Text>my second Asset Text</Text>
    </AssetText>
    <myfield>
      <Text>next myfield belongs to id 44</Text>
    </myfield>
  </ProductView>
  <ProductView>
    <ViewId>45</ViewId>
    <AssetText>
      <Text>my third Asset Text</Text>
    </AssetText>
    <myfield>
      <Text>first myfield belongs to id 45</Text>
    </myfield>
  </ProductView>
  </member>
</Product>";
            XDocument xmldoc = XDocument.Parse(xmlstr);
            IEnumerable<XElement> pvsel = xmldoc.Root.Element("member").Elements("ProductView").Where(pv => pv.Element("ViewId").Value == "44");
            IEnumerable<string> ats = pvsel.Elements("AssetText").Select(elm => elm.Element("Text").Value);
            IEnumerable<string> mfs = pvsel.Elements("myfield").Select(elm => elm.Element("Text").Value);
            List<Data> alld = ats.Zip(mfs, (at,mf) => new Data { AssetText=at, MyField=mf }).ToList();
            foreach(Data d in alld)
            {
                Console.WriteLine(d.AssetText + " : " + d.MyField);
            }
            Console.ReadKey();
        }
    }
}
Avatar billede arne_v Ekspert
17. november 2012 - 03:11 #6
Og det var lidt nemmere hvis din XML var paenere:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;

namespace E
{
    public class Data
    {
        public string AssetText { get; set; }
        public string MyField { get; set; }
    }
    public class Program
    {
        public static void Main(string[] args)
        {
            string xmlstr = @"<Product>
  <member>
  <ProductView>
    <ViewId>44</ViewId>
    <pair>
    <AssetText>
      <Text>my first Asset Text</Text>
    </AssetText>
    <myfield>
      <Text>first myfield belongs to id 44</Text>
    </myfield>
    </pair>
    <pair>
    <AssetText>
      <Text>my second Asset Text</Text>
    </AssetText>
    <myfield>
      <Text>next myfield belongs to id 44</Text>
    </myfield>
    </pair>
  </ProductView>
  <ProductView>
    <ViewId>45</ViewId>
    <pair>
    <AssetText>
      <Text>my third Asset Text</Text>
    </AssetText>
    <myfield>
      <Text>first myfield belongs to id 45</Text>
    </myfield>
    </pair>
  </ProductView>
  </member>
</Product>";
            XDocument xmldoc = XDocument.Parse(xmlstr);
            IEnumerable<XElement> pvsel = xmldoc.Root.Element("member").Elements("ProductView").Where(pv => pv.Element("ViewId").Value == "44");
            List<Data> alld = pvsel.Elements("pair").Select(p => new Data { AssetText = p.Element("AssetText").Element("Text").Value, MyField = p.Element("myfield").Element("Text").Value }).ToList();
            foreach(Data d in alld)
            {
                Console.WriteLine(d.AssetText + " : " + d.MyField);
            }
            Console.ReadKey();
        }
    }
}
Avatar billede Greenland Nybegynder
19. november 2012 - 13:02 #7
Hej Arne, tak for eksempler,
Ja xml´en kunne godt trænge til at se anderledes ud, men den kommer fra et andet system som jeg ikke kan ændre:-(

Må jeg spørge hvor Zip i ats.Zip(mfs, (at,mf) er defineret?
Hvad skulle der stå isteden for ?

Dit første eksempel fra 16. november 2012 kl. 16:08:29 (det med select new X)
virkede umiddelbart perfekt, indtil jeg lagde mærke til at resultatet/outputtet ikke var korrekt:

my first Asset Text first myfield belongs to id 44
my second Asset Text first myfield belongs to id 44
my first Asset Text next myfield belongs to id 44
my second Asset Text next myfield belongs to id 44
my third Asset Text first myfield belongs to id 45

i dit nye eksempel hvor xml´en er justeret er det korrekt:
my first Asset Text : first myfield belongs to id 44
my second Asset Text : next myfield belongs to id 44
my third Asset Text : first myfield belongs to id 45


.. jeg forsøger om jeg kan få det samme til at virke med den "gamle" xml struktur

tak
:greenland:
Avatar billede arne_v Ekspert
19. november 2012 - 13:47 #8
Zip er en del af LINQ
Avatar billede Greenland Nybegynder
20. november 2012 - 09:52 #9
Hej Arne, ok tak, jeg kørte framework 3.5. zip er en del af f 4.0

Smider du et svar...

Lige på falderebet, så har jeg svært ved at finde ud af hvor man skal starte en aflæsning i et xml document. I mit hoved burde man i linq blot kunne fyre en sql sætning af på givne columns,  hvorefter den selv fandt ud af at returnere værdierne, men det er måske for meget forlangt:-)

Hvordan ved jeg i følgende xml hvor jeg skal starte for at få fat på alle conformation (id,accountnumber,type)?Det forekommer mig svært at finde ud af:-( ellers tak for hjælpen...

<?xml version="1.0" encoding="UTF-8"?>
<batchresult>
  <outputs>
    <output>
      <value>
        <conformation>
          <component>
            <name>cmdinfo</name>
            <value>
              <bundle>
                <data>
                  <value>
                    <state>100</state>
                  </value>
                </data>
              </bundle>
            </value>
          </component>
          <component>
            <name>resultlist</name>
            <value>
              <bundle>
                <data>
                  <value>
                    <conformation>
                      <component>
                        <name>id</name>
                        <value>
                          <state>1</state>
                        </value>
                      </component>
                      <component>
                        <name>accountnumber</name>
                        <value>
                          <string>10505749</string>
                        </value>
                      </component>
                      <component>
                        <name>type</name>
                        <value>
                          <string>subnumber</string>
                        </value>
                      </component>
                    </conformation>
                  </value>
                  <value>
                    <conformation>
                      <component>
                        <name>id</name>
                        <value>
                          <state>2</state>
                        </value>
                      </component>
                      <component>
                        <name>accountnumber</name>
                        <value>
                          <string>53871265</string>
                        </value>
                      </component>
                      <component>
                        <name>type</name>
                        <value>
                          <string>subnumber</string>
                        </value>
                      </component>
                    </conformation>
                  </value>
                </data>
              </bundle>
            </value>
          </component>
          <component>
            <name>batchnumber</name>
            <value>
              <bundle>
                <data>
                  <value>
                    <state>14512367</state>
                  </value>
                </data>
              </bundle>
            </value>
          </component>
        </conformation>
      </value>
    </output>
  </outputs>
</batchresult>
Avatar billede arne_v Ekspert
20. november 2012 - 16:11 #10
Ah - jeg checkede ikke lige hvornaar den blev introduceret.

Men metoden er triviel at implementere.
Avatar billede arne_v Ekspert
20. november 2012 - 16:11 #11
og et svar
Avatar billede arne_v Ekspert
20. november 2012 - 16:14 #12
Du kan vel bruge Descendants, men jeg vil klart anbefale at arbejde dig ned gennem strukturen, fordi saa ved du hvad du faar.
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester