XQuery devolviendo error en baseX

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??

preguntado el 11 de mayo de 12 a las 05:05

4 Respuestas

/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

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

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

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 or haz tu propia pregunta.