XPath con escenario de empresa con departamentos e empregados
Sumario
Enunciado
Partimos deste XML.
<?xml version="1.0" encoding="UTF-8"?>
<empresa>
<departamento cod_dep="cont">
<telefono>981111111</telefono>
<nome>contabilidade</nome>
<empregado cod_emp="cont_001">
<nome>Xose</nome>
<dni>11111111A</dni>
<salario>4100</salario>
</empregado>
<empregado cod_emp="cont_002">
<nome>Alba</nome>
<dni>22222222B</dni>
<salario>8100</salario>
</empregado>
</departamento>
<departamento cod_dep="publ">
<telefono>982222222</telefono>
<nome>publicidade</nome>
<empregado cod_emp="publ_001">
<nome>Xoana</nome>
<dni>33333333C</dni>
<salario>1200</salario>
</empregado>
<empregado cod_emp="publ_002">
<nome>Brais</nome>
<dni>44444444D</dni>
<salario>3100</salario>
</empregado>
</departamento>
</empresa>
Descritores do camiño - rutas absolutas e relativas
Debemos saber que os descritores do camiño:
- Serven para seleccionar elementos que se atopan en certo camiño da árbore.
- fórmanse nomeando etiquetas separadas por /
- Se o descriptor comeza por / é un camiño desde a raiz
- Se o descriptor comeza por // o camiño descrito pode comezar en calquera parte da árbore
- ambos poden ser combinados
1. Selecciona a listaxe de todas as etiquetas nome de todos os empregados da empresa
/empresa/departamento/empregado/nome
Resultado:
<nome>Xose</nome>
<nome>Alba</nome>
<nome>Xoana</nome>
<nome>Brais</nome>
2. Selecciona toda as etiquetas nome en calquer nivel de profundidade do documento.
//nome
Resultado:
Amosará tanto nomes de departamentos como de empregados:
<nome>contabilidade</nome>
<nome>Xose</nome>
<nome>Alba</nome>
<nome>publicidade</nome>
<nome>Xoana</nome>
<nome>Brais</nome>
3. Proba:
//empregado/nome
Resultado:
O mesmo que no punto 1, xa que selecciona todos os nodos nome que son fillos do nodo empregado na árbore, partindo desde calquer punto
4. Selecciona o salario de tres xeitos distintos
Tres posibles expresións son:
- /empresa/departamento/empregado/salario
- //salario
- /empresa//salario
Descritores do camiño - operador *
O asterisco (*) emprégase para nomear calquera etiqueta (úsase coma comodín).
5. Selecciona a listaxe de todas as etiquetas nome que se atopan a dous niveles de profundidade desde a raiz
/*/*/nome
Resultado:
Amosa só os nomes dos departamentos.
<nome>contabilidade</nome>
<nome>publicidade</nome>
6. Qué devolve a seguinte expresión?
/*/*/*/nome
Resultado:
<nome>Xose</nome>
<nome>Alba</nome>
<nome>Xoana</nome>
<nome>Brais</nome>
Descritores do camiño - atributos
Úsase a @ para referirse os atributos. Nun descritor de camiño, os atributos noméanse coma se foran etiquetas fillas, pero antepoñendo o caracter @.
7. Selecciona os cod_dep dos departamentos da empresa
/empresa/departamento/@cod_dep
O atributo é tratado coma se fora un fillo do elemento departamento, e precedido do símbolo / e co símbolo @
Resultado:
cod_dep="cont"
cod_dep="publ"
Predicados - Filtrando conxuntos de nodos
As expresiones XPath permiten a selección de nodos nunha árbore XML. Co filtrado de expresións mediante predicados podemos seleccionar grupos de nodos que responden a criterios máis complexos, definindo o acceso aos nodos dun xeito máis preciso.
Cando un nodo se corresponde co predicado da expresión (cúmprese a condición do mesmo), éste pasará a formar parte do resultado. Se a condición non se cumpre excluirase o nodo del resultado.
Pódense empregar tamén funcións construidas (last, count, etc.) e expresións matemáticas (+, -, * div, etc.).
Además do filtrado mediante operadores relacionales e booleanos, es posible restrinxir a selección mediante una disposición en serie de predicados: os predicados en cascada, que funcionan coma unha superposición de filtros.
En primeiro lugar fíltrase un conxunto de nodos, que será a súa vez predicado, e así sucesivamente.
Finalmente, en ocasións pode ser preciso unir varios conxuntos de nodos (co pipe, "|", coa tecla Alt Gr e o número 1 do teclado).
8. Selecciona os nodos empregado para os que teñen un salario inferior a 4000
/empresa/departamento/empregado[salario<4000]
Resultado:
<empregado cod_emp="publ_001">
<nome>Xoana</nome>
<dni>33333333C</dni>
<salario>1200</salario>
</empregado>
<empregado cod_emp="publ_002">
<nome>Brais</nome>
<dni>44444444D</dni>
<salario>3100</salario>
</empregado>
9. Selecciona os nomes dos empregados do departamento co atributo cod_dep igual a publ
//departamento[@cod_dep='publ']/empregado/nome
Resultado:
<nome>Xoana</nome>
<nome>Brais</nome>
10. Selecciona os DNI do primeiro elemento departamento do documento
/empresa/departamento[1]/empregado/dni
Resultado:
<dni>11111111A</dni>
<dni>22222222B</dni>
11. Selecciona os nif dos empregados do penúltimo departamento
/empresa/departamento[last()-1]/empregado/dni
Resultado: O mesmo que no anterior, xa que no exemplo temos dous departamentos, o penúltimo é tamén o primeiro ;)
<dni>11111111A</dni>
<dni>22222222B</dni>
12. Selecciona os nomes dos empregados que teñen menos de cinco caracteres.
//empregado[string-length(nome) <5 ]/nome
Resultado:
<nome>Xose</nome>
<nome>Alba</nome>
13. Selecciona o nome dos empregados que comezan por X
//empregado[starts-with(nome,'X')]/nome
Resultado:
<nome>Xose</nome>
<nome>Xoana</nome>
14. Conta o número de departamentos do documento
count(//departamento)
Resultado: 2
15. Conta o número de empregados do documento
count(//empregado)
Resultado: 4
16. Selecciona o código de departamento dos que teñen menos de tres empregados
//departamento[count(empregado)<3]/@cod_dep
Resultado:
cod_dep="cont"
cod_dep="publ"
17. Selecciona os empregados do departamento de publicidade que cobren máis de 2000 e todos os empregados do departamento de contabilidade
//departamento[@cod_dep='publ']/empregado[salario>2000] | //departamento[@cod_dep='cont']/empregado
Eixos (axes) - sintaxe abreviada e non abreviada
Temos visto os descriptores de camiños que baixan pola árbore. En xeneral un camiño parte na raíz da árbore e logo executa unha secuencia de pasos para percorrer a árbore a atopar os nodoes que se precisan.
En cada paso se puede seguir unha de varias direccións (axes, eixos en galego). A dirección por defecto é child:: que significa seguir por calquera dos fillos do elemento actual.
Así:
- a expresión /empresa/departamento é realmente unha forma abreviada da expresión /empresa/child::departamento . Esta última sintaxe expresa claramente o desexo de seguir polos fillos da empresa.
- o símbolo @ é tam´´en unha abreviación da dirección attribute:: .
- a expresión /empresa/departamento[@cod_dep='publ'] é unha forma abreviada desta outra expresión: /empresa/child::departamento[attribute::cod_dep='publ'].
Existen moitas outras direccións:
- descendant:: para seleccionar os descendentes do nodo actual
- descendant-or-self:: para seleccionar o nodo actual e todos os seus descendientes (// é a versión abreviada desta dirección)
- ancestor:: para seleccionar todos os antepasados (pais, avós, etc.) do nodo actual
- ancestor-or-self:: para seleccionar o nodo actual e todos os antepasados (pais, avós, etc.)
- parent:: para seguir polos pais dun elemento
- following, following-sibling, etc.
Tes no titorial de w3schools explicacións con exemplos.
17. Selecciona con sintaxe non abreviada o nome do departamento do empregado 22222222C
//empregado[nif='22222222C']/parent::node()/nome
Resultado:
<nome>contabilidade</nome>
18. Selecciona con sintaxe non abreviada a totalidade do nodo pai (departamento)
//empregado[nif='22222222C']/parent::node()/nome
19. Selecciona con sintaxe non abreviada os elementos nome descendentes do elemento empresa (serán no noso caso os nomes de departamentos e empregados)
/empresa/descendant::nome
Resultado:
<nome>contabilidad</nome>
<nome>Xose</nome>
<nome>Alba</nome>
<nome>publicidad</nome>
<nome>Xoana</nome>
<nome>Brais</nome>
20. Qué devolve a seguinte expresión?
//empregado[nome='Xoana']/following-sibling::empregado
Resultado:
<empregado cod_emp="publ_002">
<nome>Brais</nome>
<dni>44444444D</dni>
<salario>3100</salario>
</empregado>
21. Qué devolve a seguinte expresión?
//empregado[nome='Xose']/preceding-sibling::empregado
Resultado:
Non atopará ningún resultado porque Xose é o primeiro.