7.1.4 - Processar el resultat
En els exemples anteriors hem processat de forma molt bàsica el resultat. Hem recorregut el XQResultSequence, per a traure tot el contingut de cada element, passant-lo a String
En realitat XQJ ens ofereix més possibilitats, que ara veurem de forma resumida.
Moviment
XQJ ens permet els següents mètodes de moviment o relacionats amb el moviment:
next(), previous(), first(), last(), beforeFirst(), afterLast(), getPosition(), isLast(), isFirst(), isAfterLast(), isBeforeFirst(), count()
Tots ells són de fàcil comprensió. L'únic problema és que la connexió ha de permetre el moviment en les dues direccions. Per defecte només es pot anar cap avant (forward only). Es pot canviar modificant les propietats de la connexió per a que siga SCROLLTYPE_SCROLLABLE, com es veu en el següent exemple, que és una modificació dels exercicis anteriors per a recórrer de forma inversa. Guardeu-lo en el fitxer Kotlin Prova3_XQJ.kt:
import net.xqj.exist.ExistXQDataSource
import javax.xml.xquery.XQResultItem
import javax.xml.xquery.XQConstants
fun main() {
val s = ExistXQDataSource()
val conn = s.getConnection()
println("Connexió feta")
val sent = "for \$alumne in //alumne order by \$alumne/cognoms return \$alumne"
val cntxt = conn.getStaticContext()
cntxt.setScrollability(XQConstants.SCROLLTYPE_SCROLLABLE)
conn.setStaticContext(cntxt)
val cons = conn.prepareExpression(sent)
val rs = cons.executeQuery()
rs.afterLast()
while (rs.previous())
println(rs.getItemAsString(null))
conn.close()
}
Obtenció del contingut
Si volem traure ja directament contingut de text, per exemple els cognoms dels alumnes, podem endur-nos alguna sorpresa. Per exemple, el següent exemple per a traure els cognoms dels alumnes per ordre alfabètic, que podeu gaurdar amb el nom Prova4_XQJ.kt:
import net.xqj.exist.ExistXQDataSource
import javax.xml.xquery.XQResultItem
import javax.xml.xquery.XQConstants
fun main() {
val s = ExistXQDataSource()
val conn = s.getConnection()
val sent = "//alumne/cognoms/text()"
val rs = conn.createExpression().executeQuery(sent)
while (rs.next())
println(rs.getItemAsString(null))
conn.close()
}
No ens traurà el text tan senzill com ens pensàvem, sinó que l'eixida serà:
text { "Alegre" }
text { "Balaguer" }
text { "Centelles" }
indicant-nos que el resultat són nodes de text. Ho podem solucionar d'una forma molt senzilla utilitzant la funció xs:string(), que ho converteix a string normal. Únicament canviant la sentència per aquesta:
val sent = "//alumne/cognoms/xs:string(text())"
el resultat ja serà el que preteníem:
Alegre
Balaguer
Centelles
També tenim una sèrie de mètodes per a obtenir el contingut que ve en un determinat format (numèric, ...) de forma adequada:
getInt(), getBoolean(), getByte(), getDouble(), ...
Però hem de fer que des de la consulta vinga la informació ja en el format adequat. El següent exemple agafa únicament les notes dels alumnes. I aquesta informació ve de forma numèrica (amb la funció xs:int() ), aleshores podem utilitzar getInt() . Guardeu el següent codi amb el nom Prova5_XQJ.kt
import net.xqj.exist.ExistXQDataSource
import javax.xml.xquery.XQResultItem
import javax.xml.xquery.XQConstants
fun main() {
val s = ExistXQDataSource()
val conn = s.getConnection()
val sent = "for \$alumne in //alumne return xs:int(\$alumne/nota/text())"
val rs = conn.createExpression().executeQuery(sent)
while (rs.next())
println(rs.getInt())
conn.close()
}
6
3
8
Però encara serà més interessant que quan ens vinga un element, poder analitzar i extraure els seus subelements, atributs, ...
Per a poder fer açò ens valdrem dels documents DOM, vistos en el tema 3. Per a poder passar la informació utilitzarem el mètode getObject()
En el següent exemple, de la consulta obtenim els element, que passem a un element DOM. Posteriorment extraurem la informació del nom, cognoms i nota. Guardeu-lo amb el nom Prova6_XQJ.kt:
import net.xqj.exist.ExistXQDataSource
import org.w3c.dom.Element
fun main() {
val s = ExistXQDataSource()
val conn = s.getConnection()
val sent ="for \$alumne in //alumne order by \$alumne/cognoms return \$alumne"
val cons = conn.prepareExpression (sent)
val rs = cons.executeQuery ()
while (rs.next()) {
val el = rs.getObject () as Element
print(el.getElementsByTagName("nom").item(0).getFirstChild().getNodeValue() + " ")
print(el.getElementsByTagName("cognoms").item(0).getFirstChild().getNodeValue() + ": ")
println(el.getElementsByTagName("nota").item(0).getFirstChild().getNodeValue())
}
conn.close()
}
Albert Alegre: 6
Bernat Balaguer: 3
Joan Centelles: 8
Un altre exemple interessant pot ser guardar un fitxer amb una determinada informació (transformada) d'un document guardat en la Base de Dades. Guardeu-lo amb el nom Prova7_XQJ.kt :
import net.xqj.exist.ExistXQDataSource
import java.io.File
import java.io.IOException
fun main() {
val f = File("notes.xml")
val s = ExistXQDataSource()
val conn = s.getConnection()
val sent = "for \$classe in /classe " +
"return <notes><modul nom=\"{\$classe/assignatura/text()}\">" +
"{for \$alumne in \$classe//alumne " +
"order by \$alumne/cognoms " +
"return <alumne nota=\"{\$alumne/nota/text()}\">" +
"{concat(\$alumne/nom/text(), \" \", \$alumne/cognoms)}" +
"</alumne>}</modul></notes> "
val cons = conn.prepareExpression (sent)
val rs = cons.executeQuery ()
var text ="<?xml version='1.0' ?>\n"
while (rs.next()) {
val linia = rs.getItemAsString (null)
println(linia)
text += linia
}
f.writeText(text)
conn.close()
}
El resultat serà el següent fitxer notes.xml (a banda que també eixirà per l'eixida estàndar):
<?xml version='1.0'?>
<notes>
<modul nom="Llenguatges de Marques" xmlns="">
<alumne nota="6" xmlns="">Albert Alegre</alumne>
<alumne nota="3" xmlns="">Bernat Balaguer</alumne>
<alumne nota="8" xmlns="">Joan Centelles</alumne>
</modul>
</notes>
que com es veu, està ben format. Aquesta seria la visualització des d'un navegador:

Llicenciat sota la Llicència Creative Commons Reconeixement NoComercial CompartirIgual 2.5