Programování

Dotazy na objekty Java pomocí JXPath

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ěstnanecs 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ěstnanecs 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, Ukazatels 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 UkazatelVý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 Ukazatelje 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í Ukazatels 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í Ukazatelsa 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.