XQuery возвращает ошибку в baseX

Ниже представлен файл 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>

Я хочу перечислить Chapters / Chapter / Name = Introduction и Chapters / Chapter / Heads / Head / No = 1 Ниже приводится запрос, который я выполняю в baseX:

/ Chapters / Chapter [содержит (Name, 'Introduction') и содержит (Heads / Head / No, '1')] / Heads / Head / Title

И это ошибка -

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.

Согласно веб-сайту baseX, описание ошибки XPTY0004 -

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).

Что я делаю не так?


person Community    schedule 11.05.2012    source источник


Ответы (4)


Это решило бы цель

/Chapters/Chapter[Name='Introduction']/Heads/Head[No='1']/Title

но я не могу ответить на ваш вопрос ... т.е. я не могу объяснить, почему ваш запрос привел к ошибке !!

person John    schedule 11.05.2012

/Chapters/Chapter
   [contains(Name,'Introduction') 
  and 
   contains(Heads/Head/No,'1')
   ]
     /Heads/Head/Title

Первый аргумент contains() должен быть одной строкой, но для второй ссылки на contains() в приведенном выше выражении аргумент Heads/Head/No оценивается как два элемента.

Исправление выражения будет:

/Chapters/Chapter
   [Name[contains(.,'Introduction')]
  and 
   Heads/Head/No[contains(.,'1')]
   ]
     /Heads/Head/Title

Замечание: похоже, что вам действительно нужно проверить равенство, а не сдерживание. Это можно выразить разными способами, одним из которых является:

/Chapters/Chapter
   [Name eq 'Introduction']
  and 
   Heads/Head/No[. eq '1']
   ]
     /Heads/Head/Title
person Dimitre Novatchev    schedule 11.05.2012

fn:contains($arg1 as xs:string?, $arg2 as xs:string?) as xs:boolean проверяет, содержится ли строка символов $arg2 в $arg1. Он ожидает одиночных строк для каждого аргумента (или пустого значения ()).

Шаг пути (здесь: Heads/Head/Title) возвращает все подходящие элементы, то есть все заголовки всех заголовков. Если вы удалите вторую часть главы «Введение», ваш запрос будет успешно выполнен.

contains - это неправильный способ сделать это. = сравнивает по заданной семантике. Используйте решение Джона или то, которое ближе к вашему (но, вероятно, решение Джона будет быстрее):

/Chapters/Chapter[Name='Introduction' and Heads/Head/No='1']/Heads/Head/Title
person Jens Erat    schedule 11.05.2012

Просто продолжение для полноты картины, и другие, справляющиеся с той же проблемой:

Ваш код не будет работать, как уже указывалось, contains не принимает последовательность строк в качестве своего первого аргумента.

(: ssce: :)
let $doc := <doc>
            <a>
              <b>foo</b>
              <b>bar</b>
            </a>
          </doc>
return $doc/a[contains(b, "bar")]

Но есть легкая конструкция, чтобы преодолеть это.

(: 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")]

Эти так называемые количественные выражения (some $var in expr и every $var in expr) являются кратким способом чтобы выразить то, что вы на самом деле делаете.

person michael    schedule 21.05.2012