Craeg Strong
Craeg Strong

Reputation: 165

Validate XML with namespaces against Schematron using lxml in Python

I am not able to get lxml Schematron validator to recognize namespaces. Validation works fine in code without namespaces.

This is for Python 3.7.4 and lxml 4.4.0 on MacOS 10.15

Here is the schematron file

<?xml version='1.0' encoding='UTF-8'?>
<schema xmlns="http://purl.oclc.org/dsdl/schematron"
  xmlns:ns1="http://foo">
  <pattern>
    <rule context="//ns1:bar">
      <assert test="number(.) = 2">
       bar must be 2
      </assert>
    </rule>
  </pattern>
</schema>

and here is the xml file

<?xml version="1.0" encoding="UTF-8"?>
<zip xmlns:ns1="http://foo">
    <ns1:bar>3</ns1:bar>
</zip>

here is the python code

from lxml import etree, isoschematron
from plumbum import local
schematron_doc = etree.parse(local.path('rules.sch'))
schematron = isoschematron.Schematron(schematron_doc)
xml_doc = etree.parse(local.path('test.xml'))
is_valid = schematron.validate(xml_doc)
assert not is_valid 

What I get: lxml.etree.XSLTParseError: xsltCompilePattern : failed to compile '//ns1:bar'

If I remove ns1 from both the XML file and the Schematron file, the example works perfectly-- no error message.

There must be a trick to registering namespaces in lxml Schematron that I am missing. Has anyone done this?

Upvotes: 4

Views: 853

Answers (1)

Craeg Strong
Craeg Strong

Reputation: 165

As it turns out, there is a specific way to register namespaces in Schematron. It is described in the Schematron ISO standard

It only required a small change to the Schematron file, adding the "ns" element in as follows:

<?xml version='1.0' encoding='UTF-8'?>
<schema xmlns="http://purl.oclc.org/dsdl/schematron">
  <ns uri="http://foo" prefix="ns1"/>
  <pattern>
    <rule context="//ns1:bar">
      <assert test="number(.) = 2">
       bar must be 2
      </assert>
    </rule>
  </pattern>
</schema>

I won't remove the question, since there is a dearth of examples of Schematron rules using namespaces. Hopefully it can be helpful to someone.

Upvotes: 4

Related Questions