Avatar billede it-dyret Nybegynder
21. august 2008 - 16:29 Der er 15 kommentarer og
1 løsning

XPath forespørgsel med 2 attributter

Jeg har følgende xml, hvor jeg gerne vil kunne finde f.eks. teksten "Annuller" ved et enkelt XPath opslag. Jeg tænkte, at jeg kunne bruge følgende udtryk, og trække TextContent ud fra noden, men jeg finder ingen node...

"//Language/Group[@name='General']/String[@name='Cancel']"

Hvordan gør jeg det så??

<Language>
  <Group name="General">
    <String name="Ok">Ok</String>
    <String name="Cancel">Annuller</String>
  </Group>
  <Group name="Login">
    <String name="Username">Brugernavn</String>
    <String name="Password">Adgangskode</String>
  </Group>
</Language>
Avatar billede softspot Forsker
21. august 2008 - 16:46 #1
Det ser da umiddelbart korrekt ud... der må være nogle andre omstændigheder som gør at du ikke får fat i en node. Kan du vise hvordan du forsøger at udføre denne XPath?
Avatar billede it-dyret Nybegynder
28. august 2008 - 12:29 #2
Jeg har en metode, som ser således ud, hvor "root" er rod Element i dokumentet (og instansvariabel), som er indlæst:

  public String getString(String group, String key){
    String xpathSelector = "//Language/Group[@name='" + group + "']/String[@name='" + key + "']";
    XPath xpath = XPathFactory.newInstance().newXPath();
    NodeList nodeList;
    try {
      nodeList = (NodeList)xpath.evaluate(xpathSelector, root, XPathConstants.NODESET);
      if(nodeList != null) {
        Element element = (Element)nodeList.item(0);
        Node n = element;
        return n.getTextContent();
      }
    }
    catch(XPathExpressionException e) {
      e.printStackTrace();
    }
    return key;
  }

Der bliver smidt en NullPointerException, idet 'n' er null, altså i linjen "return n.getTextContent();"
Avatar billede it-dyret Nybegynder
28. august 2008 - 12:32 #3
Gør jeg det uden XPath fungerer det:

  public String getString(String group, String key){
    NodeList elements = root.getElementsByTagName("Group");
    for(int i=0; i < elements.getLength(); i++){
      String groupCandidate = elements.item(i).getAttributes().item(0).getTextContent();
      if(stringGroupCandidate.equals(group)){       
        NodeList children = ((Element)elements.item(i)).getElementsByTagName("String");
        for(int c=0; c < children.getLength(); c++){
          String stringCandidate = children.item(c).getAttributes().item(0).getTextContent();
          if(stringCandidate.equals(key)){
            return children.item(c).getTextContent();
          }         
        }
      }
    }
    return key;
  }
Avatar billede it-dyret Nybegynder
28. august 2008 - 12:32 #4
Spørgsmålet er så, hvordan jeg får XPath metoden til at virke...
Avatar billede softspot Forsker
28. august 2008 - 12:47 #5
Hmm... umiddelbart noget i stil med dette (jeg er dog ikke helt sikker på om dette er den præcise syntaks):

  public String getString(String group, String key){
    try {
      XmlNode xNod = root.DocumentElement.SelectSingleNode("//Language/Group[@name='" + group + "']/String[@name='" + key + "']");

      if(xNod != null)
        return xNod.getTextContent();
    }
    catch(Exception e) {
      // whatever...
    }
    return key;
  }
Avatar billede it-dyret Nybegynder
28. august 2008 - 13:31 #6
Hmm... jeg kan slet ikke få det til at compile. Hvilken parser er det, at du anvender??

Jeg forsøger at bruge DOM (tror jeg nok, at den hedder). Jeg importerer i hvert fald javax.xml.parsers, javax.xml.transform og javax.xml.xpath
Avatar billede softspot Forsker
28. august 2008 - 13:40 #7
Ach sooo... Jeg sidder og koder i C#... :-)

Jeg kan desværre ikke hjælpe dig med Java - sorry.
Avatar billede it-dyret Nybegynder
28. august 2008 - 13:45 #8
Ah, ja det er bedst, hvis vi snakker samme sprog ;)

Men tak for forsøget... andre bud er meget velkomne!
Avatar billede arne_v Ekspert
28. august 2008 - 15:31 #9
Der er et eller andet mystisk her.

Jeg proevede med din XML fil og foelgende kode:

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathFactory;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

public class XPathFun {
    public static void main(String[] args) throws Exception {
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        DocumentBuilder db = dbf.newDocumentBuilder();
        Document doc = db.parse("C:\\xpathfun.xml");
        XPath xpath = XPathFactory.newInstance().newXPath();
        NodeList list = (NodeList)xpath.evaluate("//Language/Group[@name='General']/String[@name='Cancel']", doc.getDocumentElement(), XPathConstants.NODESET);
        Element elm = (Element)list.item(0);
        System.out.println(elm.getTextContent());
    }
}

Den virker !!

Check indholdet af:
- xpathSelector
- root
Avatar billede arne_v Ekspert
28. august 2008 - 15:32 #10
Og saa ville jeg aldrig bruge .getTextContext() !
Avatar billede it-dyret Nybegynder
16. september 2008 - 11:36 #11
Først og fremmest vil jeg beklage den lange responstid...

Og dernæst, så har du fuldstændig ret i, Arne V, at der er noget mystisk. Og det mystiske viste sig at være en fejl i xml'en, mens koden hele tiden har fungeret, som den burde! :S

Men smid et svar, så jeg kan belønne dig for at guide mig ind på sporet!

Og hvorfor ville du aldrig bruge .getTextContext()? Hvad ville du bruge i stedet for?
Avatar billede arne_v Ekspert
16. september 2008 - 12:08 #12
svar
Avatar billede arne_v Ekspert
16. september 2008 - 12:09 #13
getTextContent() returnerer al text ogsaa fra undernoder, saa det taber strukturen.

Jeg ville lade XPath'en vaelge den text jeh skulle bruge.
Avatar billede it-dyret Nybegynder
16. september 2008 - 12:13 #14
Oh, du kan vel ikke lige demonstrere, hvordan jeg gør det, når det altid blot er elementets tekst, at jeg skal have fat i? Se evt. eksemplet ovenfor...
Avatar billede arne_v Ekspert
16. september 2008 - 12:36 #15
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathFactory;

import org.w3c.dom.Document;
import org.w3c.dom.Node;

public class XPathFun {
    public static void main(String[] args) throws Exception {
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        DocumentBuilder db = dbf.newDocumentBuilder();
        Document doc = db.parse("C:\\xpathfun.xml");
        XPath xpath = XPathFactory.newInstance().newXPath();
        Node cantxt = (Node)xpath.evaluate("//Language/Group[@name='General']/String[@name='Cancel']/text()", doc.getDocumentElement(), XPathConstants.NODE);
        System.out.println(cantxt.getNodeValue());
    }
}
Avatar billede it-dyret Nybegynder
16. september 2008 - 13:12 #16
Jeg takker og bukker :)
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
Kategori
Kurser inden for grundlæggende programmering

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