Fórum Root.cz

Hlavní témata => Vývoj => Téma založeno: Dr.Who 27. 03. 2015, 14:01:05

Název: Vytažení dat z XML v Javě
Přispěvatel: Dr.Who 27. 03. 2015, 14:01:05
Cau,
prostrednictvim podobneho kodu http://www.java2s.com/Code/JavaAPI/org.w3c.dom/ElementNodeListgetChildNodes.htm (http://www.java2s.com/Code/JavaAPI/org.w3c.dom/ElementNodeListgetChildNodes.htm)  jsem zkousel z nasledujiciho XML dostat hodnotu z promenne ct na radku CS id="3", ale beznadejne.

Kód: [Vybrat]
<Snapshot id="142102345">
<Stats name="runtime" statType="moduleRuntime" il="-2">
<CS id="2" sT="1422004481541" lST="1427376591432" ct="225331">
</CS>
<CS id="3" sT="1422004481541" lST="1427376591432" ct="503459"> 
</CS>
<CS id="5" sT="1422004481541" lST="1427376591432" ct="0">
</Stats>
</Snapshot>

Je nejaka jina cesta nez getChildNodes, ktera mi pomuze vytahat hodnoty ct?
Název: Re:vytahnuti dat z XML
Přispěvatel: Zaprdeny deda 27. 03. 2015, 14:26:25
Jakou knihovnu na XML pouzivas? Je jich vic, jedna je naprosto debilni a nema na to funkce, jina umoznuje pristup primo na konkretni childnode, kdyz znas jeho jmeno. Uz je to dlouho, co jsem to pouzival, najdi si jak to ruzny knihovny resi.
Název: Re:vytahnuti dat z XML
Přispěvatel: Zaprdeny deda 27. 03. 2015, 14:27:38
Aha, w3c.org neni ta nejlepsi XML knihovna.
Název: Re:vytahnuti dat z XML
Přispěvatel: Filip Jirsák nepřihlášený 27. 03. 2015, 14:38:36
XPath. Pro Javu existují různé implementace, např. Jaxen, Saxon. Také pro práci s XML existují vhodnější knihovny, než W3C DOM – DOM4J, JDOM, XOM.

Např. v DOM4J použijete přibližně takovýhle kód:
Kód: [Vybrat]
result = document.selectSingleNode("/Snapshot/Stats/CS[@id='3']/@ct");
Název: Re:Vytažení dat z XML v Javě
Přispěvatel: Dr.Who 07. 04. 2015, 09:54:24
Povedlo se mi pomoci jednoho prikladu na netu dostat prvni hodnoty ze souboru XML. Potrebuji ale v jednom "for" dostat vicero hodnot atributu.
Pokousel sem se Xpath rozsirit, ale bez uspechu


Kód: [Vybrat]

         XPath xPath =  XPathFactory.newInstance().newXPath();

         String expression = "//Stats[@name='jvmRuntimeModule']/CS[@id='2'] | //Stats[@name='systemModule']/CS[@id='1'] | //Stats[@name='connectionPoolModule']/RS[@id='9']";
         NodeList nodeList = (NodeList) xPath.compile(expression).evaluate(doc, XPathConstants.NODESET);
         for (int i = 0; i < nodeList.getLength(); i++) {
            Node nNode = nodeList.item(i);
            System.out.println("\nCurrent Element :"
               + nNode.getNodeName());
            if (nNode.getNodeType() == Node.ELEMENT_NODE) {
               Element eElement = (Element) nNode;

               System.out.println("Value : "
                  + eElement.getAttribute("ct") + eElement.getAttribute("ct") + eElement.getAttribute("cur"));
                System.out.println("*****************************************");
            }


         }




Název: Re:Vytažení dat z XML v Javě
Přispěvatel: Filip Jirsák nepřihlášený 07. 04. 2015, 11:36:19
Ten XPath výraz máte správně.

S dom4j by to bylo

Kód: [Vybrat]
List<Element> elements = (List<Element>) document.selectNodes(
    "//Stats[@name='jvmRuntimeModule']/CS[@id='2'] |" +
    "//Stats[@name='systemModule']/CS[@id='1'] | " +
    "//Stats[@name='connectionPoolModule']/RS[@id='9']"
);
for (Element element : elements) {
  System.out.printf("Value: %s%s%s",
      element.attributeValue("ct"),
      element.attributeValue("ct"),
      element.attributeValue("cur")
    ).println();
  System.out.println("*****************************************");
}

S W3C DOM vám asi nikdo neporadí, protože to nikdo nepoužívá. Není důvod používat tohle složité API, když existuje spousta alternativ, které toho umějí víc a jsou mnohem jednodušší na použití.
Název: Re:Vytažení dat z XML v Javě
Přispěvatel: Dr.Who 07. 04. 2015, 17:38:16
Ten XPath výraz máte správně.

S dom4j by to bylo

Kód: [Vybrat]
List<Element> elements = (List<Element>) document.selectNodes(
    "//Stats[@name='jvmRuntimeModule']/CS[@id='2'] |" +
    "//Stats[@name='systemModule']/CS[@id='1'] | " +

);
for (Element element : elements) {
  System.out.printf("Value: %s%s%s",
      element.attributeValue("ct"),
      element.attributeValue("ct"),
 
    ).println();
  System.out.println("*****************************************");
}

S W3C DOM vám asi nikdo neporadí, protože to nikdo nepoužívá. Není důvod používat tohle složité API, když existuje spousta alternativ, které toho umějí víc a jsou mnohem jednodušší na použití.

Dekuju moc! Akorat mam problem, ze se mi nedari zmenit vystup

dostavam:


24440 24440
*********************************
65  65 
*********************************

Jak muzu donutit for, abych mel na radku oboje hodnoty? tzn

24440[to je hodnota prvniho ct]  65[hodnota druheho ct]
Název: Re:Vytažení dat z XML v Javě
Přispěvatel: Filip Jirsák nepřihlášený 07. 04. 2015, 18:21:44
V tom vašem příkladu jste vypisoval dvakrát za sebou hodnotu jednoho atributu u stejného elementu. Nedávalo mi to smysl, ale opsal jsem to tak i do mého řešení.

Jaké „oboje hodnoty“ tam chcete mít? Každý element může mít pouze jeden atribut daného jména.

Ty XPtah výrazy, které jste napsal, neodpovídají tomu XML na začátku. Nejlepší by bylo, kdybyste sem dal celé XML nebo alespoň jeho relevantní část, a napsal, co z něj vlastně chcete získat.
Název: Re:Vytažení dat z XML v Javě
Přispěvatel: Dr.Who 08. 04. 2015, 08:45:31
Kód: [Vybrat]
<TPVLog>
<Snapshot time="1422004481541">
<Stats name="jvmRuntimeModule" statType="jvmRuntimeModule#" il="-2" type="COLLECTION">
<CS id="2" sT="1422004481541" lST="1427376440605" ct="234457">
</CS>
<Stats name="systemModule" statType="systemModule" il="-2" type="MODULE">
<CS id="1" sT="1427192170123" lST="1427376470956" ct="61">
</CS>
</Snapshot>
</TPVLog>

Je jich tam pod sebou vice to je jenom pro ilustraci. Atribut CT v kazdem nodu?  vyjadruje pozadovanou hodnotu, kterou si potrebuju vyexportovat

Název: Re:Vytažení dat z XML v Javě
Přispěvatel: Zdenek Henek 08. 04. 2015, 09:46:11
Je jich tam pod sebou vice to je jenom pro ilustraci. Atribut CT v kazdem nodu?  vyjadruje pozadovanou hodnotu, kterou si potrebuju vyexportovat

Jestli jich je tam opravdu hodne(stovky MB)  a toto neni jen domaci ukol do skoly s tim, ze uz to nikdy neuvidite, tak bych doporucoval pouzit Sax nebo Stax knihovnu a zpracovavat xml postupne, aby to nespotrebovalo zbytecne moc pameti. Tyto knihovny jsou slozitejsi na pouziti, ale pokud to xml ve finale bude opravdu velke, tak jinou rozumnou moznost nevidim.

https://docs.oracle.com/javase/tutorial/jaxp/sax/parsing.html
https://docs.oracle.com/javase/tutorial/jaxp/stax/why.html

Dalsi moznost je JAXB. http://www.oracle.com/technetwork/articles/javase/index-140168.html
Pokud mate schema tak muzete xml parser vygenerovat a pak uz jen pouzivat java objekty. Toto jsem nikdy nepouzil na velkych xml souborech. Pouzival jsem Stax parser a ve chvili, kdy jsem narazil na element, ktery mel slozitou strukturu(ale nebyl velky), tak jsem pouzil JAXB.

Jeste k tomu schema. Pokud zadne nemate, tak doporucuji vytvorit a pouzivat. Cloveku nic nezkazi den vic nez zjisteni, ze uz par hodin hleda chybu v kodu a vstupni xml je starsi verze :)
Název: Re:Vytažení dat z XML v Javě
Přispěvatel: j 08. 04. 2015, 09:46:55
Kód: [Vybrat]
<TPVLog>
<Snapshot time="1422004481541">
<Stats name="jvmRuntimeModule" statType="jvmRuntimeModule#" il="-2" type="COLLECTION">
<CS id="2" sT="1422004481541" lST="1427376440605" ct="234457">
</CS>
<Stats name="systemModule" statType="systemModule" il="-2" type="MODULE">
<CS id="1" sT="1427192170123" lST="1427376470956" ct="61">
</CS>
</Snapshot>
</TPVLog>

Je jich tam pod sebou vice to je jenom pro ilustraci. Atribut CT v kazdem nodu?  vyjadruje pozadovanou hodnotu, kterou si potrebuju vyexportovat

Vsak jo, cyklus bezi pres ty radky, tak ze v kazdym cyklu lze vypsat jednu hodnotu, ne 2, 3, 4 ...
Název: Re:Vytažení dat z XML v Javě
Přispěvatel: perceptron 08. 04. 2015, 11:23:37
nepovedali ste co to je za zadanie. chcete vsetky ct alebo len pre dany riadok?

jaxb je na tento task overkill

riesenie cez stream sax

https://gist.github.com/anonymous/0757f4f1c6c11fe0f026
Název: Re:Vytažení dat z XML v Javě
Přispěvatel: Filip Jirsák nepřihlášený 08. 04. 2015, 11:35:23
Pro každý element Snapshot tedy chcete vypsat tu trojici?

Kód: [Vybrat]
Element root = document.getRootElement();
for (Element snapshotElement : (List<Element>) root.elements("Snapshot")) {
    System.out.printf("Value: %s%s%s",
      snapshotElement.selectObject("Stats[@name='jvmRuntimeModule']/CS[@id='2']/@ct"),
      snapshotElement.selectObject("Stats[@name='systemModule']/CS[@id='1']/@ct"),
      snapshotElement.selectObject("Stats[@name='connectionPoolModule']/RS[@id='9']/@cur")
    ).println();
  System.out.println("*****************************************");
}

Dá se to optimalizovat, ty XPath výrazy se nemusí parsovat v každé iteraci cyklu, ale je možné si je vytvořit předem a v cyklu volat xpath1.evaluate(snapshotElement).

Pokud by ty XML soubory byly velké (stovky MB), stejně nedoporučuju používat SAX nebo StAX, protože jsou to zbytečně nízkoúrovňová API a to samé se dá zvládnout i s vysokoúrovňovými knihovnami. Např. s dom4j se dá použít ElementHandler:

Kód: [Vybrat]
SAXReader reader = new SAXReader();
reader.addHandler( "/TPVLog/Snapshot",
    new ElementHandler() {
        public void onStart(ElementPath path) {
            // Jsme na začátku elementu, neděláme nic
        }
        public void onEnd(ElementPath path) {
            Element snapshotElement = path.getCurrent();
            //Tady už máme zkonstruovaný strom pro element Snapshot, takže na něm můžeme zavolat úplně ten samý kód, jako v prvním příkladu:
            System.out.printf("Value: %s%s%s",
              snapshotElement.selectObject("Stats[@name='jvmRuntimeModule']/CS[@id='2']/@ct"),
              snapshotElement.selectObject("Stats[@name='systemModule']/CS[@id='1']/@ct"),
              snapshotElement.selectObject("Stats[@name='connectionPoolModule']/RS[@id='9']/@cur")
            ).println();
            System.out.println("*****************************************");

            //zpracovaný element odstraníme z dokumentu, aby zbytečně nezabíral místo
            snapshotElement .detach();
        }
    }
);

Document document = reader.read(url);
//z dokumentu zbyla jen obálka, ale to nevadí, můžeme ho zahodit
Název: Re:Vytažení dat z XML v Javě
Přispěvatel: tdvorak 08. 04. 2015, 12:18:53
Aby tu nebylo těch variant málo, přihodím mou s jsoup (http://jsoup.org/) knihovnou. Člověk pak může k datům přistupovat stejně, jako třeba v JQuery - pomocí CSS selectorů.

https://gist.github.com/todvora/490895c9e596e51f88d1

Název: Re:Vytažení dat z XML v Javě
Přispěvatel: Dr.Who 13. 04. 2015, 14:30:31
Pro každý element Snapshot tedy chcete vypsat tu trojici?

Kód: [Vybrat]
Element root = document.getRootElement();
for (Element snapshotElement : (List<Element>) root.elements("Snapshot")) {
    System.out.printf("Value: %s%s%s",
      snapshotElement.selectObject("Stats[@name='jvmRuntimeModule']/CS[@id='2']/@ct"),
      snapshotElement.selectObject("Stats[@name='systemModule']/CS[@id='1']/@ct"),
      snapshotElement.selectObject("Stats[@name='connectionPoolModule']/RS[@id='9']/@cur")
    ).println();
  System.out.println("*****************************************");
}

Dá se to optimalizovat, ty XPath výrazy se nemusí parsovat v každé iteraci cyklu, ale je možné si je vytvořit předem a v cyklu volat xpath1.evaluate(snapshotElement).

Pokud by ty XML soubory byly velké (stovky MB), stejně nedoporučuju používat SAX nebo StAX, protože jsou to zbytečně nízkoúrovňová API a to samé se dá zvládnout i s vysokoúrovňovými knihovnami. Např. s dom4j se dá použít ElementHandler:

Kód: [Vybrat]
SAXReader reader = new SAXReader();
reader.addHandler( "/TPVLog/Snapshot",
    new ElementHandler() {
        public void onStart(ElementPath path) {
            // Jsme na začátku elementu, neděláme nic
        }
        public void onEnd(ElementPath path) {
            Element snapshotElement = path.getCurrent();
            //Tady už máme zkonstruovaný strom pro element Snapshot, takže na něm můžeme zavolat úplně ten samý kód, jako v prvním příkladu:
            System.out.printf("Value: %s%s%s",
              snapshotElement.selectObject("Stats[@name='jvmRuntimeModule']/CS[@id='2']/@ct"),
              snapshotElement.selectObject("Stats[@name='systemModule']/CS[@id='1']/@ct"),
              snapshotElement.selectObject("Stats[@name='connectionPoolModule']/RS[@id='9']/@cur")
            ).println();
            System.out.println("*****************************************");

            //zpracovaný element odstraníme z dokumentu, aby zbytečně nezabíral místo
            snapshotElement .detach();
        }
    }
);

Document document = reader.read(url);
//z dokumentu zbyla jen obálka, ale to nevadí, můžeme ho zahodit

Ano, presne tak. Zkusil sem pouzit tu prvni moznost

Element root = document.getRootElement();
for (Element snapshotElement : (List<Element>) root.elements("Snapshot")) {
    System.out.printf("Value: %s%s%s",
      snapshotElement.selectObject("Stats[@name='jvmRuntimeModule']/CS[@id='2']/@ct"),
      snapshotElement.selectObject("Stats[@name='systemModule']/CS[@id='1']/@ct"),
      snapshotElement.selectObject("Stats[@name='connectionPoolModule']/RS[@id='9']/@cur")
    ).println();
  System.out.println("*****************************************");
}
[/code]

prislo mi to nejjednodussi a vzhledem k mojim dovednostem Javy jako cesta nejmensiho odporu. Akorat na vystupu dostavam
pocet radku reprezentujici pocet nodu <stats> ale hodnoty, ktere se maji vytahnout jsou prazdne. Uz jsem zkousel i ruzne pomenit ty cesty, ale bez vysledku.

Co se XML tyce tak to je jeste cele ohranicene tagem TPVlog, zkousel sem si jeste hrat s tim, ze sem zmenil root elements na TPVLog ale bez uspechu.