#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
с префиксом пространства имен, я попробовал следующее, которое успешно работает:
-
В file.xml Я опустил
aid
префикс из атрибутовaid:trows
иaid:tcol
, связанных сtable
, как показано ниже:... <table trows="3" tcols="2"> ... </table>
-
Затем переопределено:
- функция XPath
count
в правиле Schematron какcount(./Cell) = @trows * @tcols
- и определил атрибуты для
table
astrows
и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> ...
- функция XPath
Ответ №1:
Вот несколько вариантов:
-
Префиксы пространства имен, используемые в тестах assert в Schemetron, должны быть объявлены с использованием элемента Schematron
ns
. Добавьте следующее в качестве первого дочернего элемента<grammar>
в схеме RelaxNG:<sch:ns prefix="aid" uri="http://ns.adobe.com/AdobeInDesign/4.0/"/>
-
Кроме того, вы можете утвердить пространство имен атрибутов в тесте assert с помощью функции XPath
namespace-uri()
. Изменить:@aid:trows
Для:
@*:trows[namespace-uri() = 'http://ns.adobe.com/AdobeInDesign/4.0/']
(и то же самое для
tcols
). -
Или, если вы ленивы, вы можете использовать
@*:trows
, который будет выбиратьtrows
атрибуты любого пространства имен.