Выражение XPath с использованием idref

Я читаю о XQuery и тестирую его, и в качестве инструментов тестирования я использую BaseX (www.basex.org) и saxon-HE 9.4.0.6N. Для следующего простого XML-файла — схема не привязана к sample.xml:

    <rootab>
     <l1>
       <items p="a">
         <itema x1="10" id="abc">testa</itema>
         <itemb x1="10" id="dfe">testb</itemb>
         <itemc x1="10" id="jgh">testc</itemc>  
       </items>
     </l1> 
     <l2>
         <items p="b">
           <itema x1="10" xidref="abc">testa</itema>
           <itemc x1="10" xidref="jgh">testc</itemc>  
           <itemd x1="10" xidref="abc">testA101</itemd>  
           <iteme x1="10" xidref="jgh">testB202</iteme>  
         </items>
     </l2> 
</rootab>

В Basex_GUI, если я введу следующее выражение XPath: //idref("abc")/.., результат будет: <itema x1="10" xidref="abc">testa</itema>

В BaseX_GUI, если я добавлю простое выражение XQuery:

for $x in doc('sample.xml')//idref("abc")/.. 
    return <aaa>{$x}</aaa>

результат:

<aaa>
  <itema x1="10" xidref="abc">testa</itema>
</aaa>
<aaa>
  <itemd x1="10" xidref="abc">testA101</itemd>
 </aaa>

q1) Почему выражение XPath вернуло только один узел? Я ожидал два...

В Saxon, используя приведенный ниже файл xql:

    <test>
    {
    doc('sample.xml')//idref("abc")/..
    }
   </test>

или выражение XQuery, я получаю тот же результат, выполнив команду query sample.xql:

<?xml version="1.0" encoding="UTF-8"?><test/>

q2) что не так в моем саксонском тесте?

Заранее спасибо за вашу помощь!


person dag    schedule 05.12.2012    source источник


Ответы (1)


По сути, idref() чувствителен к проверке DTD — он распознает атрибуты, объявленные как тип IDREF в вашем DTD.

Вы не показали нам свой DTD и, что более важно, не показали, как подаются входные данные для запросов. Существует множество способов создания входных данных, в которых теряется "IDREF-ность" атрибута - например, при переходе через DOM. Даже когда вы используете функцию doc() в Saxon, способ построения входного дерева зависит от многих факторов, включая параметры конфигурации и ваш URIResolver.

Я вижу, вы используете .NET. Когда Saxon использует синтаксический анализатор Microsoft XML в .NET, он не знает, какие атрибуты являются идентификаторами и IDREF, поэтому функции id() и idref() не работают (парсер MS просто не предоставляет эту информацию). Поэтому вам необходимо использовать синтаксический анализатор JAXP (Xerces), поставляемый с продуктом Saxon. Я думаю, что это по умолчанию в наши дни.

Так что на самом деле это не ответ, но, надеюсь, некоторая предыстория, объясняющая некоторые вещи, которые могут пойти не так.

person Michael Kay    schedule 05.12.2012
comment
нет DTD... образец.xml был написан после того, как я прочитал несколько глав в вашей книге. - person dag; 05.12.2012
comment
Если нет ни DTD, ни схемы, то система не может узнать, какие атрибуты являются атрибутами IDREF, поэтому функция idref() никогда ничего не вернет. - person Michael Kay; 05.12.2012
comment
если я напишу свой собственный DTD, можно ли использовать его (внутренний DTD или внешнюю ссылку) из командной строки с Saxon? (например, запрос -useDTD:x sample.xql). А программно, в .Net? Файл DTD должен быть довольно простым, только то, что мне нужно - некоторые атрибуты должны быть объявлены как тип IDREF. Большое спасибо! - person dag; 05.12.2012