Правило утверждения Schematron, встроенное в RelaxNG, приводит к необъявленной ошибке префикса пространства имен

#xml #schematron #relaxng

#xml #schematron #relaxng

Вопрос:

Пример кода

Рассмотрим следующий несколько надуманный экземпляр XML:

file.xml

 <?xml version="1.0" encoding="UTF-8"?>
<section xmlns:aid="http://ns.adobe.com/AdobeInDesign/4.0/" xmlns:aid5="http://ns.adobe.com/AdobeInDesign/5.0/">
  <table aid:trows="3" aid:tcols="2">
    <Cell>header column 1</Cell>
    <Cell>header column 2</Cell>
    <Cell>row 1 column 1</Cell>
    <Cell>row 1 column 2</Cell>
    <Cell>row 2 column 1</Cell>
    <Cell>row 2 column 2</Cell>
  </table>
</section>
  

Он успешно проверяется с использованием следующей схемы Relax NG:

schema.rng

 <?xml version="1.0" encoding="UTF-8"?>
<grammar xmlns="http://relaxng.org/ns/structure/1.0"
  datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes"
  xmlns:sch="http://purl.oclc.org/dsdl/schematron"
  xmlns:aid="http://ns.adobe.com/AdobeInDesign/4.0/"
  xmlns:aid5="http://ns.adobe.com/AdobeInDesign/5.0/">
  <start>
    <ref name="section"/>
  </start>
  <define name="section">
    <element name="section">
      <ref name="table"/>
    </element>
  </define>
  <define name="table">
    <sch:pattern name="Test attributes aid:rows and aid:tcols when multiplied equal count of Cell elements">
      <sch:rule context="table">
        <sch:assert test="count(./Cell) = 6">Count of Cell elements does not match specified @aid:rows and @aid:tcols.</sch:assert>
      </sch:rule>
    </sch:pattern>
    <element name="table">
      <attribute name="aid:trows">
        <data type="integer"/>
      </attribute>
      <attribute name="aid:tcols">
        <data type="integer"/>
      </attribute>
      <oneOrMore>
        <element name="Cell">
          <text/>
        </element>
      </oneOrMore>
    </element>
  </define>
</grammar>
  

Примечание: встроенное правило Schematron в schema.rng , то есть часть, которая гласит следующее:

 <sch:pattern name="Test attributes aid:rows and aid:tcols when multiplied equal count of Cell elements">
 <sch:rule context="table">
   <sch:assert test="count(./Cell) = 6">Count of Cell elements does not match specified @aid:rows and @aid:tcols.</sch:assert>
 </sch:rule>
</sch:pattern>
  

Это правило assert гласит, что количество Cell узлов элемента должно быть равно 6 :

Что я пытаюсь сделать?

Я пытаюсь избежать жесткого кодирования того, какое количество Cell элементов должно быть в функции XPath count , которая в настоящее время определена в правиле Schematron. т.е. В этой части (снова показано ниже) указано, что количество Cell элементов должно быть шесть:

 <sch:assert test="count(./Cell) = 6">...</sch:assert>
                                  ^
  

Что я хочу сделать, так это определить, каким Cell должно быть количество элементов, путем умножения значений атрибутов aid:trows и aid:tcols , связанных с table элементом. т.Е. Вывести его из этих атрибутов в file.xml показано снова ниже:

 <table aid:trows="3" aid:tcols="2">
                  ^             ^
  ...
</table>
  

What have I tried…

I’ve tried redefining the XPath count function in the Schematron rule as follows.

 <sch:assert test="count(./Cell) = @aid:trows * @aid:tcols">...</sch:assert>
  

Однако попытка проверки file.xml выдает следующую ошибку (кстати. Я использую редактор XML Oxygen):

 Failed to compile stylesheet. 1 error detected.
Undeclared namespace prefix {aid}
Got a fatal error trying to create a transformer from the stylesheet!
  

Похоже, есть какая-то проблема с aid префиксом пространства имен!

Что я здесь недопонимаю? Как я могу это исправить?

Что работает?

Чтобы определить, связано ли это aid с префиксом пространства имен, я попробовал следующее, которое успешно работает:

  1. В file.xml Я опустил aid префикс из атрибутов aid:trows и aid:tcol , связанных с table , как показано ниже:

     ...
    <table trows="3" tcols="2">
        ...
    </table>
      
  2. Затем переопределено:

    • функция XPath count в правиле Schematron как count(./Cell) = @trows * @tcols
    • и определил атрибуты для table as trows и tcols , т. Е. опустил aid: префиксы.

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

     ...
    <define name="table">
      <sch:pattern name="Test attributes aid:rows and aid:tcols when multiplied equal count of Cell elements">
        <sch:rule context="table">
          <!-- change below -->
          <sch:assert test="count(./Cell) = @trows * @tcols">Count of Cell elements does not match specified @aid:rows and @aid:tcols.</sch:assert>
        </sch:rule>
      </sch:pattern>
      <element name="table">
        <!-- change below -->
        <attribute name="trows">
          <data type="integer"/>
        </attribute>
        <!-- change below -->
        <attribute name="tcols">
          <data type="integer"/>
        </attribute>
        <oneOrMore>
          <element name="Cell">
            <text/>
          </element>
        </oneOrMore>
      </element>
    </define>
    ...
      

Ответ №1:

Вот несколько вариантов:

  1. Префиксы пространства имен, используемые в тестах assert в Schemetron, должны быть объявлены с использованием элемента Schematron ns . Добавьте следующее в качестве первого дочернего элемента <grammar> в схеме RelaxNG:

    <sch:ns prefix="aid" uri="http://ns.adobe.com/AdobeInDesign/4.0/"/>

  2. Кроме того, вы можете утвердить пространство имен атрибутов в тесте assert с помощью функции XPath namespace-uri() . Изменить:

    @aid:trows

    Для:

    @*:trows[namespace-uri() = 'http://ns.adobe.com/AdobeInDesign/4.0/']

    (и то же самое для tcols ).

  3. Или, если вы ленивы, вы можете использовать @*:trows , который будет выбирать trows атрибуты любого пространства имен.