XQuery devolviendo error en baseX
Frecuentes
Visto 1,235 veces
3
A continuación se muestra el archivo XML:
<Chapters>
<Chapter>
<Name>Introduction</Name>
<Heads>
<Head>
<No>1</No>
<Title>History of Internet</Title>
<Desc>
..............
</Desc>
</Head>
<Head>
<No>2</No>
<Title>History of HTML</Title>
<Desc>
..............
</Desc>
</Head>
</Heads>
</Chapter>
<Chapter>
<Name>Learn HTML</Name>
<Heads>
<Head>
<No>1</No>
<Title>Browsers</Title>
<Desc>
..............
</Desc>
</Head>
<Head>
<No>2</No>
<Title>Browser War</Title>
<Desc>
..............
</Desc>
</Head>
<Head>
<No>3</No>
<Title>HTML, DHTML</Title>
<Desc>
..............
</Desc>
</Head>
</Heads>
</Chapter>
</Chapters>
Quiero listar los Capítulos/Capítulo/Nombre=Introducción y Capítulos/Capítulo/Encabezados/Encabezado/No=1 La siguiente es la consulta que estoy ejecutando en baseX:
/Capítulos/Capítulo[contiene(Nombre,'Introducción') y contiene(Encabezados/Encabezado/No,'1')]/Encabezados/Encabezado/Título
Y este es el error -
Query: Chapters/Chapter[contains(Name,'Introduction') and contains(Heads/Head/No,'1')]/Heads/Head/Title
Error: [XPTY0004] Single item expected, (element No { ... }, element No { ... }) found.
Según el sitio web de baseX, la descripción del error XPTY0004 es:
This error is raised if an expression has the wrong type, or cannot be cast into the specified type. It may be raised both statically (during query compilation) or dynamically (at runtime).
Que mal estoy haciendo??
4 Respuestas
4
/Chapters/Chapter
[contains(Name,'Introduction')
and
contains(Heads/Head/No,'1')
]
/Heads/Head/Title
El primer argumento de contains()
debe ser una sola cadena pero para la segunda referencia a contains()
en la expresión anterior, el argumento Heads/Head/No
evalúa a dos elementos.
Una corrección de la expresión sería:
/Chapters/Chapter
[Name[contains(.,'Introduction')]
and
Heads/Head/No[contains(.,'1')]
]
/Heads/Head/Title
Observación: Parece que realmente necesita probar la igualdad, no la contención. Esto se puede expresar de muchas maneras, una de las cuales es:
/Chapters/Chapter
[Name eq 'Introduction']
and
Heads/Head/No[. eq '1']
]
/Heads/Head/Title
contestado el 11 de mayo de 12 a las 13:05
2
fn:contains($arg1 as xs:string?, $arg2 as xs:string?) as xs:boolean
prueba si la cadena de caracteres $arg2
está contenido en $arg1
. Espera cadenas individuales para cada argumento (o el valor vacío ()
).
Un paso de ruta (aquí: Heads/Head/Title
) devuelve todos los elementos que encajan, por lo que todos los títulos de todos los encabezados. Si elimina el segundo encabezado del Capítulo "Introducción", su consulta se ejecutará correctamente.
contains
es la manera incorrecta de hacer esto. =
compara en una semántica establecida. Use la solución de John o esta que se parece más a la suya (pero la de John probablemente sea más rápida):
/Chapters/Chapter[Name='Introduction' and Heads/Head/No='1']/Heads/Head/Title
contestado el 11 de mayo de 12 a las 08:05
2
Solo un seguimiento en aras de la exhaustividad y otros que se enfrentan al mismo problema:
Su código no funcionará, como ya se señaló contains
no acepta una secuencia de cadenas como primer argumento.
(: ssce: :)
let $doc := <doc>
<a>
<b>foo</b>
<b>bar</b>
</a>
</doc>
return $doc/a[contains(b, "bar")]
Pero hay una construcción fácil de superar esto.
(: ssce, this time working: :)
let $doc := <doc>
<a>
<b>foo</b>
<b>bar</b>
</a>
</doc>
return $doc/a[some $b in b/text() satisfies contains($b, "bar")]
Estos llamados expresiones cuantificadas (some $var in expr
y every $var in expr
) son una forma concisa de expresar lo que realmente estás haciendo.
contestado el 21 de mayo de 12 a las 12:05
1
Este resolvería el propósito.
/Chapters/Chapter[Name='Introduction']/Heads/Head[No='1']/Title
pero no puedo responder a su pregunta... es decir, ¡no puedo explicar por qué su consulta resultó en un error!
contestado el 11 de mayo de 12 a las 07:05
No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas xpath xquery basex or haz tu propia pregunta.