V nedávném projektu jsem potřeboval snadný způsob, jak procházet stromy objektů Java a extrahovat hodnoty z objektů. Místo neustálého procházení obrovskými nastaveními iterátoru, pokud-jiného, jsem chtěl nástroj, který by mi umožnil jednoduše říci: „Chci objekt s id = X a od tohoto objektu potřebuji hodnotu vlastnosti A.“ V podstatě jsem potřeboval nástroj pro dotazování objektů.
JXPath je takový nástroj pro dotazování na objekty. Jedná se o komponentu Apache Commons, která umožňuje dotazovat se na stromy složitých objektů pomocí známého jazyka výrazu XPath. Ve svém projektu jsem široce zaměstnával JXPath a značně to urychlilo, takže algoritmy těžby hodnot byly hračkou.
JXPath však není široce dokumentován. Protože jsem každopádně hlouběji zkoumal komponentu, rozhodl jsem se napsat svá zjištění do rozsáhlého tutoriálu JXPath, který najdete na mém webu. Tento článek je zkrácenou verzí tohoto tutoriálu, který vám pomůže rychle začít s JXPath.
Poznámka: Průvodní ukázkový kód si můžete stáhnout ze zdrojů.
Příklad modelu
Pro ilustraci použijeme jednoduchý model: a společnost s různými oddělení, každý s různými zaměstnanci. Tady je model třídy:
Přirozeně potřebujeme několik ukázkových dat pro model:
Společnost | oddělení | Zaměstnanec (jméno, pracovní pozice, věk) |
Acme Inc. | Odbyt | Johnny, obchodní zástupce, 45 Sarah, obchodní zástupce, 33 Magda, kancelářská asistentka, 27 |
Účetnictví | Steve, hlavní kontrolor, 51 Peter, pomocný kontrolor, 31 Susan, kancelářská asistentka, 27 |
Když je to na místě, začněme používat JXPath!
Provádění jednoduchých dotazů JXPath
Nejjednodušší možný dotaz extrahuje jeden objekt ze stromu objektů. Například k načtení Společnost
, použijte následující kód:
Kontext JXPathContext = JXPathContext.newContext (společnost); Společnost c = (společnost) context.getValue (".");
První řádek ukazuje vytvoření a kontext
, výchozí bod pro všechny výrazy XPath JXPath ve stromu objektů (srovnatelné s rootnode
prvek v dokumentu XML). Druhý řádek kódu provede skutečný dotaz. Od našeho kontext
začíná na úrovni společnosti, získat Společnost
objektu, jednoduše použijeme selektor aktuálního prvku '.'
.
Používání predikátů a proměnných
An Zaměstnanec
je podřízeným objektem a oddělení
. Chcete-li získat Zaměstnanec
s názvem „Johnny“ použijte následující kód (Společnost
je stále kontext
(výchozí bod):
Zaměstnanec emp = (zaměstnanec) context.getValue ("/ departmentList / zaměstnanci [name = 'Johnny']" ");
V zásadě kód zní: „Hledat vše oddělení
s od začátku pro Zaměstnanec
objekt, jehož název
atribut má hodnotu 'Johnny'
."
Výše uvedený fragment kódu ukazuje, jak použít predikát k prohledávání objektů pomocí konkrétních hodnot. Použití predikátů je srovnatelné s použitím klauzule WHERE v SQL. Můžeme dokonce kombinovat více predikátů v jednom dotazu:
Zaměstnanec emp = (zaměstnanec) context.getValue ("/ departmentList / zaměstnanci [name = 'Susan' a věk = 27]");
Pokud nepoužíváte jednorázový dotaz ad-hoc, implementace pevně zakódovaných dotazů obvykle není proveditelná. Je lepší definovat opakovaně použitelný dotaz, který pak můžete provést s různými parametry. Pro přizpůsobení parametrizovaným dotazům podporuje JXPath proměnné v dotazech. Pomocí proměnných výše uvedený kód nyní vypadá takto:
context.getVariables (). declareVariable ("název"„Susan“); context.getVariables (). declareVariable ("stáří", nové celé číslo (27)); Zaměstnanec emp = (Zaměstnanec) context.getValue ("/ departmentList / zaměstnanci [jméno =$ jméno a věk =$ věk]");
Iterace nad sbírkami
JXPath může poskytnout iterátor nad všemi objekty získanými dotazem, podobně jako iterace sady výsledků. Následující úryvek ukazuje, jak můžete iterovat přes všechny oddělení
s:
pro (iterátor iter = context.iterate ("/ departmentList"); iter.hasNext ();) {Department d = (Department) iter.next (); // ...}
Chcete-li získat všechny Zaměstnanec
s ze všech oddělení
s a iterovat nad nimi:
for (Iterator iter = context.iterate („/ departmentList / zaměstnanci“); iter.hasNext ();) {Zaměstnanec emp = (Zaměstnanec) iter.next (); // ...}
Chcete-li získat všechny Zaměstnanec
s starší než 30 let z obchodního oddělení:
for (Iterator iter = context.iterate ("/ departmentList [name = 'Sales'] / zaměstnanci [věk> 30]"); iter.hasNext ();) {Zaměstnanec emp = (Zaměstnanec) iter.next (); // ...}
A výše uvedený příklad s proměnnými:
context.getVariables (). declareVariable („deptName“, "Odbyt"); context.getVariables (). declareVariable („minAge“, nové celé číslo (30)); for (Iterator iter = context.iterate ("/ departmentList [name =$ deptName] / zaměstnanci [věk>$ minVěk] "); iter.hasNext ();) {Zaměstnanec emp = (Zaměstnanec) iter.next (); // ...}
Tyto dva poslední fragmenty kódu také demonstrují použití několika predikátů v rámci jednoho dotazu XPath.
Ukazatele
A Ukazatel
je obslužný objekt JXPath, který představuje odkaz na umístění objektu ve stromu objektů. Například a Ukazatel
může odkazovat na „prvního zaměstnance druhého oddělení“. Ve srovnání s objekty získanými přímo ze stromu, Ukazatel
s nabízejí další funkce, jako je provádění relativní dotazy přes relativní kontexty (více o tom později).
Používání ukazatelů
Mít a Ukazatel
odkaz na objekt ve stromu objektů je téměř totožný s přímým načítáním objektů:
JXPathContext context = JXPathContext.newContext (společnost); Ukazatel empPtr = kontext.getPointer("/ departmentList [name = 'Sales'] / zaměstnanci [věk> 40]"); System.out.println (empPtr); //výstup: / departmentList [1] / zaměstnanci [1] System.out.println (((zaměstnanec) empPtr.getValue ()) .getName ()); //výstup: Johnny
Všimněte si, že Ukazatel
Výstup ukazuje, že a Ukazatel
popisuje místo objektu spíše než samotný objekt. Všimněte si také, že skutečný objekt Ukazatel
odkazuje na lze získat prostřednictvím Ukazatel
je getValue ()
metoda.
Ukazatele lze také iterovat, jak ukazuje následující fragment:
for (Iterator iter = kontext.iteratePointers("/ departmentList [name = 'Sales'] / zaměstnanci [věk> 30]"); iter.hasNext ();) {Ukazatel empPtr = (Ukazatel) iter.next (); // ...}
Relativní kontext a relativní dotazy
Protože a Ukazatel
popisuje místo, lze jej použít jako referenční bod pro navigaci v celém stromu objektů. K tomu použijte Ukazatel
jako kořenový objekt (Nezapomeňte použít Společnost
objekt pro to dříve?) v tzv relativní kontext. Z tohoto relativního kontextu můžete provést dotaz na celý strom objektů relativní dotazy. Toto pokročilé použití Ukazatel
s nabízí velkou flexibilitu, jak ilustrují níže uvedené příklady.
Začněte takto: relativní kontext vytvoříte takto:
for (Iterator iter = context.iteratePointers ("/ departmentList [name = 'Sales'] / zaměstnanci [věk> 30]"); iter.hasNext ();) {Ukazatel empPtr = (Ukazatel) iter.next (); JXPathContext relativeContext = context.getRelativeContext (empPtr); }
V tomto fragmentu kódu je vytvořen nový relativní kontext za sebou zaměstnanec
ukazatele.
Pomocí relativního kontextu lze dotazy XPath spouštět na celém stromě objektů sourozenců, dětí a rodičů / prarodičů, jak ukazuje následující úryvek:
// Aktuální zaměstnanec Zaměstnanec emp = (Zaměstnanec) relativeContext.getValue ("."); // Jméno zaměstnance String name = (String) relativeContext.getValue ("./ name"); // Název oddělení, ke kterému tento zaměstnanec patří (nadřazený objekt) String deptName = (String) relativeContext.getValue ("../ name"); // Název společnosti, k níž tento zaměstnanec patří (objekt 'prarodiče') String compName = (String) relativeContext.getValue ("../../ name"); // Všichni spolupracovníci tohoto zaměstnance (sourozenecké objekty) pro (Iterator empIter = relativeContext.iterate ("../ zaměstnanci"); empIter.hasNext ();) {kolega zaměstnance = (zaměstnanec) empIter.next (); // ...}
souhrn
JXPath je mimořádně užitečný nástroj pro procházení, navigaci a dotazování na stromy složitých objektů. Protože pro své dotazy používá jazyk výrazu XPath, je k dispozici velké množství referenčních materiálů, které vám pomohou vytvářet efektivní, ale složité dotazy na vyhledávání objektů. Ještě větší flexibilitu přidává použití Ukazatel
sa relativní kontexty.
Tento krátký článek pouze škrábe povrch možností JXPath, pro podrobnější diskusi s pokročilejšími příklady použití si přečtěte celý můj návod.
Bart van Riel působí v prostředí Java a objektově orientovaného světa již více než sedm let. Pracoval jako vývojář a trenér v objektově orientovaných oblastech a oblastech Java. V současné době je zaměstnán u globální IT poradenské firmy Capgemini jako softwarový architekt a protagonista open source.Další informace o tomto tématu
- Stáhněte si zdrojový kód tohoto článku
- Podívejte se na celý výukový program JXPath
- Apache Commons JXPath
- Dobrý výukový program XPath
- Projděte si články v JavaWorldje Vývojové nástroje Výzkumné centrum
- Držte krok s tím, co je nového JavaWorld! Zaregistrujte se zdarma Enterprise Java zpravodaj
Tento příběh, „Dotazy na objekty Java pomocí JXPath“, původně publikoval JavaWorld.