pythonxmllxmlxincludexpointer

XML with recursive XInclude statements


I have a problem with a recursive XInclude statement. I have a main file where an XInclude exists on another file. In the included file are further XInclude statements.

I parse my XML file with python and the library lxml. As a result I unfortunately only get the following. Where is my error? Or is a recursive use of XInlcude not desired?

Thanks for your help.

Main-File

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<TEST Id = "MyTest" xmlns:xi="http://www.w3.org/2001/XInclude" >
  <FOO>
    <BAR/>
  </FOO>
  <xi:include xpointer="element(/1/1)" href="Test_1.xml"/>
</TEST>

Fist Include

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<TEST.INCLUDE xmlns:xi="http://www.w3.org/2001/XInclude">
     <xi:include href="Test_1_1.xml" xpointer="element(/1/1)"/>
     <xi:include href="Test_1_2.xml" xpointer="element(/1/1)"/>
     <xi:include href="Test_1_3.xml" xpointer="element(/1/1)"/>
</TEST.INCLUDE>

Second Includes (Test_1_1.xml, Test_1_2.xml and Test_1_3.xml is for this example identical)

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<TEST.INCLUDE>
    <FOO Id="Test_1_1">
        <BAR/>
    </FOO>
</TEST.INCLUDE>   

My result with the following python code.

import lxml
from lxml import etree
import xml.etree.ElementTree as ET 

XMLParser               = lxml.etree.XMLParser()
XMLFile                 = lxml.etree.parse('Model.xml', parser=XMLParser)

XMLFile.xinclude()
XMLFile.write(f"Model_xinclude.xml",method="xml",pretty_print=True)

Result

<TEST xmlns:xi="http://www.w3.org/2001/XInclude" Id="MyTest">
  <FOO>
    <BAR/>
  </FOO>
  <FOO Id="Test_1_1">
    <BAR/>
  </FOO>
</TEST>

But I would have expected and wanted the following result

<TEST xmlns:xi="http://www.w3.org/2001/XInclude" Id="MyTest">
  <FOO>
    <BAR/>
  </FOO>
  <FOO Id="Test_1_1">
    <BAR/>
  </FOO>
  <FOO Id="Test_1_2">
    <BAR/>
  </FOO>
  <FOO Id="Test_1_3">
    <BAR/>
  </FOO>
</TEST>

Solution

  • In the main file (Model.xml), you have this include element:

    <xi:include xpointer="element(/1/1)" href="Test_1.xml"/>
    

    It will select only the first include element in Test_1.xml.

    To get the wanted result, you need the following in the main file:

    <xi:include xpointer="element(/1/1)" href="Test_1.xml"/>
    <xi:include xpointer="element(/1/2)" href="Test_1.xml"/>
    <xi:include xpointer="element(/1/3)" href="Test_1.xml"/>
    

    This can be simplified by using the xpointer() scheme, which requires one line:

    <xi:include xpointer="xpointer(/TEST.INCLUDE/*)" href="Test_1.xml"/>