Check alle échte Black Friday-deals Ook zo moe van nepaanbiedingen? Wij laten alleen échte deals zien

[C# / XML] Specifieke node in XmlNodeList vinden

Pagina: 1
Acties:

  • PdeBie
  • Registratie: Juni 2004
  • Laatst online: 22-11 16:59
Hoi allen,

zie het volgende deel van een xml:

XML:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
.....
<Features>
  <Feature>
    <AFMG_DISPLAYLABEL>Tekst Kaartje</AFMG_DISPLAYLABEL>
    <SLFT_FIELDTYPE>ftString</SLFT_FIELDTYPE>
    <SLFT_VALUE>sss</SLFT_VALUE>
  </Feature>
  <Feature>
    <AFMG_DISPLAYLABEL>Bezorgtijdstip</AFMG_DISPLAYLABEL>
    <SLFT_FIELDTYPE>ftLookup</SLFT_FIELDTYPE>
    <SLFT_VALUE>Voor de middag</SLFT_VALUE>
  </Feature>
</Features>
.....


Ik ben bezig om een functie te schrijven waarmee ik de SLFT_VALUE kan kan ophalen van een specifieke feature. Het kiezen van de feature zou moeten op basis van de node AFMG_DISPLAYLABEL.

Ik heb al een XmlNodeList met daarin dit 'feature-blok'. Deze maak ik aan met onderstaande code:
C#:
1
2
3
var features = paramXmlDocument.SelectNodes("//Message/MessageContent/PurchaseOrder/OrderLines/OrderLine/Features");

return GetFeatureValue(features, "Bezorgtijdstip");


Met de functie 'GetFeatureValue' wil ik de waarde ophalen. Alleen loop ik in die functie dus stuk. Want hoe kan ik nou dat ene specifieke feature ophalen waar de node AFMG_DISPLAYLABEL gelijk is aan bijvoorbeeld 'Bezorgtijdstip'?

  • MrTinux
  • Registratie: December 2000
  • Laatst online: 09:37

MrTinux

Terug van nooit weggeweest.

Waarom gebruik je als XPath-query niet:
code:
1
/Features/Feature/AFMG_DISPLAYLABEL[text()='Tekst Kaartje']/../SLFT_VALUE


Waarbij je uiteraard "Tekst Kaartje" vervangt door de variable waarop gezocht wordt (vergeet hierbij niet te controleren op XPath-injection!)

"Hij doet 't niet" = onvolledige informatie


  • Corniel
  • Registratie: April 2002
  • Laatst online: 31-03 14:56

Corniel

De wereld is gek!

Wat ook kan, en wellicht voor een breder gebruik van deze structuur is aan te bevelen, is een er een ojbectstrutuur van te maken die met Serializable is, waarbij je verschillende properties eventueel anoteert met [XmlElement("name")].

Dan kan je iets doen in de trant van:
C#:
1
var feature = features.FirstOrDefault(f => f.DisplayLabel == label);

while (me.Alive) {
me.KickAss();
}


  • PdeBie
  • Registratie: Juni 2004
  • Laatst online: 22-11 16:59
MrTinux schreef op donderdag 09 januari 2014 @ 16:19:
Waarom gebruik je als XPath-query niet:
code:
1
/Features/Feature/AFMG_DISPLAYLABEL[text()='Tekst Kaartje']/../SLFT_VALUE


Waarbij je uiteraard "Tekst Kaartje" vervangt door de variable waarop gezocht wordt (vergeet hierbij niet te controleren op XPath-injection!)
Dit xpath lijkt niet te kloppen. Ik krijg een null terug.

@Corniel:
hoe had je dit in gedachten? Kan je een voorbeeld geven?

--edit--

wat ik tot op heden heb:

C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
private static string GetFeatureValue(XmlNodeList paramNodeList, string node)
        {
            if (paramNodeList == null)
            {
                throw new ArgumentNullException("paramNodeList");
            }
            if (node == null)
            {
                throw new ArgumentNullException("node");
            }
            if (node.Trim() == String.Empty)
            {
                throw new ArgumentException("node");
            }

            foreach (XmlNode xmlNode in paramNodeList)
            {
                var xpath = string.Format("/Feature/AFMG_DISPLAYLABEL[text()='{0}']", node);
                var feature = xmlNode[xpath];
                
                //feature is hier null :(
            }

            //Tijdelijk even niets returnen.
            return String.Empty;
        }

[ Voor 46% gewijzigd door PdeBie op 09-01-2014 16:48 ]


Verwijderd

Volgens mij moet je de eerste "/" in de xpath weglaten.

Deze geeft een absoluut pad aan ipv een relatief pad.

  • Gomez12
  • Registratie: Maart 2001
  • Laatst online: 17-10-2023
pdebie schreef op donderdag 09 januari 2014 @ 16:46:
[...]
Dit xpath lijkt niet te kloppen. Ik krijg een null terug.
Dit xpath klopt met jouw voorbeeld.

Zolang features maar het root-element is klopt deze xpath

  • MrTinux
  • Registratie: December 2000
  • Laatst online: 09:37

MrTinux

Terug van nooit weggeweest.

pdebie schreef op donderdag 09 januari 2014 @ 16:46:
[...]
Dit xpath lijkt niet te kloppen. Ik krijg een null terug.
Op basis van jouw XPath-query zou het idd moeten zijn:
code:
1
//Message/MessageContent/PurchaseOrder/OrderLines/OrderLine/Features/Feature/AFMG_DISPLAYLABEL[text()='Tekst Kaartje']/../SLFT_VALUE

"Hij doet 't niet" = onvolledige informatie


  • PdeBie
  • Registratie: Juni 2004
  • Laatst online: 22-11 16:59
ok, dus ik kan niet eerst dat 'blok' features pakken en die naar de functie GetFeatureValue schieten?
Want er zitten meer van dit soort blokken in de XML, dus leek me handiger om een functie te maken waar je een specifiek blok in schiet en vervolgens daar in gaat zoeken.

GetFeatureValue zal dan dus niks anders worden dan pak het 'blok' features en schiet die door naar een functie als 'GetNodeValue(blok, gewensteNode);'


---- edit ----

Inmiddels is het gelukt met deze functie. Ga nog wel kijken of ik het kan refactoren, zodat het bruikbaar is over de gehele XML, maar dat moet wel lukken. Bedankt voor de hulp mensen :)

C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
private static string GetFeatureValue(XmlNode paramXmlNode, string node)
{
    if (paramXmlNode == null)
    {
        throw new ArgumentNullException("paramXmlNode");
    }
    if (node.Trim() == String.Empty)
    {
        throw new ArgumentException("node");
    }

    var xpath =
        string.Format(
       "//Message/MessageContent/PurchaseOrder/OrderLines/OrderLine/Features/Feature/AFMG_DISPLAYLABEL[text()='{0}']/../SLFT_VALUE"
        , node);

    XmlNode feature;
    try
    {
        feature = paramXmlNode.SelectSingleNode(xpath);
    }
    catch (XPathException xPathException)
    {
        //TODO add logging
        return String.Empty;
    }

    if (feature == null)
    {
        throw new NullReferenceException(string.Format("Feature {0} is not found", node));
    }

    return !string.IsNullOrEmpty(feature.InnerText) ? feature.InnerText : String.Empty;
}

[ Voor 90% gewijzigd door PdeBie op 10-01-2014 09:01 ]


Verwijderd

door // te gebruiken in je xpath 'kun' je resultaten terug krijgen die je misschien niet wilt, doordat hetzelfde pad misschien voorkomt onder een andere node.

Je eerde aangegeven stukje:
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
private static string GetFeatureValue(XmlNodeList paramNodeList, string node) 
        { 
            if (paramNodeList == null) 
            { 
                throw new ArgumentNullException("paramNodeList"); 
            } 
            if (node == null) 
            { 
                throw new ArgumentNullException("node"); 
            } 
            if (node.Trim() == String.Empty) 
            { 
                throw new ArgumentException("node"); 
            } 

            foreach (XmlNode xmlNode in paramNodeList) 
            { 
                var xpath = string.Format("/Feature/AFMG_DISPLAYLABEL[text()='{0}']", node); 
                var feature = xmlNode[xpath]; 
                 
                //feature is hier null :( 
            } 

            //Tijdelijk even niets returnen. 
            return String.Empty; 
        }

zou naar mijn idee moeten werken wanneer je:
C#:
1
var xpath = string.Format("/Feature/AFMG_DISPLAYLABEL[text()='{0}']", node); 

aanpast naar:
C#:
1
var xpath = string.Format("Feature/AFMG_DISPLAYLABEL[text()='{0}']", node); 


door // vooraan je xpath te zetten zoek je de door de gehele XML naar alle paden die beginnen met..

door / vooraan je xpath te zetten geef je aan dat je vanaf de root (van de xml, niet de huidige node)

wanneer je met een node-naam begint in je xpath start hij vanaf de huidige node te zoeken naar onderliggende nodes.

  • PdeBie
  • Registratie: Juni 2004
  • Laatst online: 22-11 16:59
klopt, maar ik weet dat deze resultaten niet onder een andere node voorkomen.

  • sig69
  • Registratie: Mei 2002
  • Nu online
Offtopic tipje:
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
if (node == null)  
{  
    throw new ArgumentNullException("node");  
}  
if (node.Trim() == String.Empty)  
{  
    throw new ArgumentException("node");  
}

// Zelfde:
if(string.IsNullOrWhiteSpace(node)
{
    throw new ArgumentException("node");  
}

Roomba E5 te koop


  • PdeBie
  • Registratie: Juni 2004
  • Laatst online: 22-11 16:59
alleen wil ik bij null een ArgumentNullException gooien en bij een lege string een ArgumentException ;)

  • sig69
  • Registratie: Mei 2002
  • Nu online
Ah dat had ik gemist. Het is vrijdag, ben niet zo scherp meer.. 8)7

Roomba E5 te koop

Pagina: 1