xs:include not finding included file after XSLT transformation
![](https://secure.gravatar.com/avatar/028bf1363186931aaa9dd5e4ce05682b.jpg?s=120&d=mm&r=g)
Using python-lxml-2.2.3-1.1.el6.x86_64 on RHEL6. I have a schema file using relative include statements like this: <xs:include schemaLocation="some/relative/path/blah.xsd"/> From this file an element tree object is created: schematree = etree.parse(schemafile) Then a schema object is created using: etree.XMLSchema(schematree) This works fine, the include statement is resolved relative to the locate of the schema file. Now I need to modify the schema tree object via an XSLT transformation, before the schema object is created: transform = etree.XSLT(...) schematree = transform(schematree) Now the creation of the schema object fails with the error message: lxml.etree.XMLSchemaParseError: Element '{http://www.w3.org/2001/XMLSchema}include': Failed to load the document 'some/relative/path/blah.xsd' for inclusion., line 3 I suppose this is caused by the fact that applying the XML transformation to the original element tree object creates a new element tree object (or rather _XSLTResultTree which is derived from _ElementTree), and the new object does not have a valid docinfo property. (It is empty.) So the include file is resolved relative to the current working directory, and not relative to the location of the original schema XML document. Now, is there a way to get the included file resolved relative to the location of the original schema. I tried setting the docinfo property on the result of the transformation, but this is not allowed. Is there any other way? TIA, Markus
![](https://secure.gravatar.com/avatar/8b97b5aad24c30e4a1357b38cc39aeaa.jpg?s=120&d=mm&r=g)
Am 28. September 2017 16:13:47 MESZ schrieb "Markus Schöpflin":
I have a schema file using relative include statements like this:
<xs:include schemaLocation="some/relative/path/blah.xsd"/>
From this file an element tree object is created:
schematree = etree.parse(schemafile)
Then a schema object is created using:
etree.XMLSchema(schematree)
This works fine, the include statement is resolved relative to the locate of the schema file.
Now I need to modify the schema tree object via an XSLT transformation, before the schema object is created:
transform = etree.XSLT(...) schematree = transform(schematree)
Now the creation of the schema object fails with the error message:
lxml.etree.XMLSchemaParseError: Element '{http://www.w3.org/2001/XMLSchema}include': Failed to load the document 'some/relative/path/blah.xsd' for inclusion., line 3
I suppose this is caused by the fact that applying the XML transformation to the original element tree object creates a new element tree object (or rather _XSLTResultTree which is derived from _ElementTree), and the new object does not have a valid docinfo property. (It is empty.) So the include file is resolved relative to the current working directory, and not relative to the location of the original schema XML document.
Now, is there a way to get the included file resolved relative to the location of the original schema. I tried setting the docinfo property on the result of the transformation, but this is not allowed.
Is there any other way?
You could either resolve the relative paths to absolute paths ahead of time, or set an xml:base attribute on the new document root that refers to the original document source. Stefan
![](https://secure.gravatar.com/avatar/028bf1363186931aaa9dd5e4ce05682b.jpg?s=120&d=mm&r=g)
Am 29.09.2017 um 07:32 schrieb Stefan Behnel:
Am 28. September 2017 16:13:47 MESZ schrieb "Markus Schöpflin":
I have a schema file using relative include statements like this:
<xs:include schemaLocation="some/relative/path/blah.xsd"/>
From this file an element tree object is created:
schematree = etree.parse(schemafile)
Then a schema object is created using:
etree.XMLSchema(schematree)
This works fine, the include statement is resolved relative to the locate of the schema file.
Now I need to modify the schema tree object via an XSLT transformation, before the schema object is created:
transform = etree.XSLT(...) schematree = transform(schematree)
Now the creation of the schema object fails with the error message:
[...]
You could either resolve the relative paths to absolute paths ahead of time, or set an xml:base attribute on the new document root that refers to the original document source.
Thank you very much, that did the trick. I now basically use: schematree = etree.parse(schemafile) url = schematree.docinfo.URL schematree = etree.XSLT(...)(schematree) schematree.getroot().base = url schema = etree.XMLSchema(schematree) This works like a charm. Markus
![](https://secure.gravatar.com/avatar/8b97b5aad24c30e4a1357b38cc39aeaa.jpg?s=120&d=mm&r=g)
Markus Schöpflin schrieb am 29.09.2017 um 09:21:
Am 29.09.2017 um 07:32 schrieb Stefan Behnel:
Am 28. September 2017 16:13:47 MESZ schrieb "Markus Schöpflin":
I have a schema file using relative include statements like this:
<xs:include schemaLocation="some/relative/path/blah.xsd"/>
From this file an element tree object is created:
schematree = etree.parse(schemafile)
Then a schema object is created using:
etree.XMLSchema(schematree)
This works fine, the include statement is resolved relative to the locate of the schema file.
Now I need to modify the schema tree object via an XSLT transformation, before the schema object is created:
transform = etree.XSLT(...) schematree = transform(schematree)
Now the creation of the schema object fails with the error message:
[...]
You could either resolve the relative paths to absolute paths ahead of time, or set an xml:base attribute on the new document root that refers to the original document source.
Thank you very much, that did the trick.
I now basically use:
schematree = etree.parse(schemafile) url = schematree.docinfo.URL schematree = etree.XSLT(...)(schematree) schematree.getroot().base = url schema = etree.XMLSchema(schematree)
This works like a charm.
Interesting. ;) That's not what I meant, so I wonder why it would make a difference. I meant this: https://www.w3.org/TR/xmlbase/ Stefan
![](https://secure.gravatar.com/avatar/8b97b5aad24c30e4a1357b38cc39aeaa.jpg?s=120&d=mm&r=g)
Stefan Behnel schrieb am 29.09.2017 um 09:31:
Markus Schöpflin schrieb am 29.09.2017 um 09:21:
Am 29.09.2017 um 07:32 schrieb Stefan Behnel:
Am 28. September 2017 16:13:47 MESZ schrieb "Markus Schöpflin":
I have a schema file using relative include statements like this:
<xs:include schemaLocation="some/relative/path/blah.xsd"/>
From this file an element tree object is created:
schematree = etree.parse(schemafile)
Then a schema object is created using:
etree.XMLSchema(schematree)
This works fine, the include statement is resolved relative to the locate of the schema file.
Now I need to modify the schema tree object via an XSLT transformation, before the schema object is created:
transform = etree.XSLT(...) schematree = transform(schematree)
Now the creation of the schema object fails with the error message:
[...]
You could either resolve the relative paths to absolute paths ahead of time, or set an xml:base attribute on the new document root that refers to the original document source.
Thank you very much, that did the trick.
I now basically use:
schematree = etree.parse(schemafile) url = schematree.docinfo.URL schematree = etree.XSLT(...)(schematree) schematree.getroot().base = url schema = etree.XMLSchema(schematree)
This works like a charm.
Interesting. ;) That's not what I meant, so I wonder why it would make a difference. I meant this:
Ah - it obviously works because it is a supported feature that does exactly that :D I just keep forgetting all those wonderful little things that lxml's API does for you... Stefan
![](https://secure.gravatar.com/avatar/028bf1363186931aaa9dd5e4ce05682b.jpg?s=120&d=mm&r=g)
Am 29.09.2017 um 09:35 schrieb Stefan Behnel:
Stefan Behnel schrieb am 29.09.2017 um 09:31:
Markus Schöpflin schrieb am 29.09.2017 um 09:21: [...]
Thank you very much, that did the trick.
I now basically use:
schematree = etree.parse(schemafile) url = schematree.docinfo.URL schematree = etree.XSLT(...)(schematree) schematree.getroot().base = url schema = etree.XMLSchema(schematree)
This works like a charm.
Interesting. ;) That's not what I meant, so I wonder why it would make a difference. I meant this:
Ah - it obviously works because it is a supported feature that does exactly that :D
I just keep forgetting all those wonderful little things that lxml's API does for you...
No misunderstand here, your explanation was perfectly fine. But googling for the words "lxml xml:base" lead me to http://lxml.de/api/lxml.etree._Element-class.html#base which describes exactly what you wrote in your follow-up. ;-) So I opted for that solution because it looks nice and easy to understand. Markus
participants (2)
-
Markus Schöpflin
-
Stefan Behnel