0

In the following example, test.xml shows no IntelliJ problem but test2.xml shows an Invalid id reference highlighting fooid red. Surprisingly, this is different to what happens with test3.xml where also the root elements are annotated with There is no ID/IDREF binding for IDREF 'fooid2'.

main.xsd

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">

    <xs:attributeGroup name="attributeGroup_foo">
        <xs:attribute name="id" type="xs:ID" use="required"/>
    </xs:attributeGroup>

    <xs:complexType name="complexType_foo">
        <xs:attributeGroup ref="attributeGroup_foo"/>
    </xs:complexType>

    <xs:attributeGroup name="attributeGroup_bar">
        <xs:attribute name="idref" type="xs:IDREF" use="required"/>
    </xs:attributeGroup>

    <xs:complexType name="complexType_bar">
        <xs:attributeGroup ref="attributeGroup_bar"/>
    </xs:complexType>

    <xs:complexType name="complexType_root">
        <xs:sequence>
            <xs:choice minOccurs="0" maxOccurs="unbounded">
                <xs:element name="root" type="complexType_root"/>
                <xs:element name="foo" type="complexType_foo"/>
                <xs:element name="bar" type="complexType_bar"/>
            </xs:choice>
        </xs:sequence>
    </xs:complexType>

    <xs:element name="root" type="complexType_root"/>

</xs:schema>

test.xml

<?xml version="1.0" encoding="utf-8"?>
<root
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:xi="http://www.w3.org/2001/XInclude"
        xsi:noNamespaceSchemaLocation="main.xsd">

    <foo id="fooid"/>
    <bar idref="fooid"/>

</root>

test1.xml

<?xml version="1.0" encoding="utf-8"?>
<root
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:xi="http://www.w3.org/2001/XInclude"
        xsi:noNamespaceSchemaLocation="main.xsd">

    <foo id="fooid"/>

</root>

test2.xml

<?xml version="1.0" encoding="utf-8"?>
<root
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:xi="http://www.w3.org/2001/XInclude"
        xsi:noNamespaceSchemaLocation="main.xsd">

    <xi:include href="test1.xml" parse="xml">
        <xi:fallback/>
    </xi:include>

    <bar idref="fooid"/>

</root>

test3.xml

<?xml version="1.0" encoding="utf-8"?>
<root
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:xi="http://www.w3.org/2001/XInclude"
        xsi:noNamespaceSchemaLocation="main.xsd">

    <xi:include href="test1.xml" parse="xml">
        <xi:fallback/>
    </xi:include>

    <bar idref="fooid2"/>

</root>

I am wondering why the ID from test1 is not available in test2. Possibly this is an XY problem: maybe I am misusing XML/XSD and should solve my problem differently? What would be the best practice here?

My goal is basically to define parts of a bigger XML file in separate XML files and to include them to avoid code duplicates if e.g. some parts are imported multiple times into different other XML files (e.g. some basic part that is imported in 10 or so other xml files that then have nothing to do with each other). Parsing those XML files also currently works but I am not happy with the red highlighting.

1 Answers1

0

You need to add the xpointer attribute to the include, to only add the specified element, else the include will add the whole xml file which will cause a schema validation error.

<xi:include href="test1.xml" parse="xml" xpointer="fooid">
    <xi:fallback/>
</xi:include>

If you use this construct the result of the combined output looks like this:

<foo id="fooid" xml:base="test1.xml"/>

Then your xml schema will fail because the "xml:base" attribute is not declared there. if you import the required w3 namespace and add a ref attribute it will work.

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xml="http://www.w3.org/XML/1998/namespace"> 
<xs:import namespace="http://www.w3.org/XML/1998/namespace" schemaLocation="http://www.w3.org/2001/03/xml.xsd" />
    <xs:attributeGroup name="attributeGroup_foo">
        <xs:attribute name="id" type="xs:ID" use="required"/>
        <xs:attribute ref="xml:base"/>
    </xs:attributeGroup>

update:

after the comment you posted regarding having a lot of key value pairs that need to be included via xpointer I changed the layout of your xml schema so it will accept a list and this works fine.

main.xsd

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xml="http://www.w3.org/XML/1998/namespace">
    <xs:import namespace="http://www.w3.org/XML/1998/namespace" schemaLocation="http://www.w3.org/2001/03/xml.xsd"/>
    <xs:attributeGroup name="attributeGroup_foo">
        <xs:attribute name="id" type="xs:ID" use="required"/>
        <xs:attribute ref="xml:base"/>
    </xs:attributeGroup>
    <xs:attributeGroup name="attributeGroup_foolist">
        <xs:attribute name="id" type="xs:ID" use="required"/>
        <xs:attribute ref="xml:base"/>
    </xs:attributeGroup>
    <xs:complexType name="complexType_foo">
        <xs:attributeGroup ref="attributeGroup_foo"/>
    </xs:complexType>
    <xs:attributeGroup name="attributeGroup_bar">
        <xs:attribute name="idref" type="xs:IDREF" use="required"/>
    </xs:attributeGroup>
    <xs:complexType name="complexType_bar">
        <xs:attributeGroup ref="attributeGroup_bar"/>
    </xs:complexType>
    <xs:complexType name="complexType_foolist">
        <xs:sequence>
            <xs:choice minOccurs="0" maxOccurs="unbounded">
                <xs:element name="foolist" type="complexType_foolist"/>
                <xs:element name="foo" type="complexType_foo"/>
                <xs:element name="bar" type="complexType_bar"/>
            </xs:choice>
        </xs:sequence>
        <xs:attributeGroup ref="attributeGroup_foolist"/>
    </xs:complexType>
    <xs:complexType name="complexType_root">
        <xs:sequence>
            <xs:choice minOccurs="0" maxOccurs="unbounded">
                <xs:element name="foolist" type="complexType_foolist"/>
                <xs:element name="foo" type="complexType_foo"/>
                <xs:element name="bar" type="complexType_bar"/>
            </xs:choice>
        </xs:sequence>
    </xs:complexType>
    <xs:element name="root" type="complexType_root"/>
</xs:schema>

test1.xml

<?xml version="1.0" encoding="utf-8"?>
<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xi="http://www.w3.org/2001/XInclude" xsi:noNamespaceSchemaLocation="main.xsd">
    <foolist id="foolist">
        <foo id="fooid"/>
        <foo id="fooid1"/>
        <foo id="fooid2"/>
    </foolist>
</root>

test2.xml

<?xml version="1.0" encoding="utf-8"?>
<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xi="http://www.w3.org/2001/XInclude" xsi:noNamespaceSchemaLocation="main.xsd">
    <xi:include href="test1.xml" parse="xml" xpointer="foolist">
        <xi:fallback/>
    </xi:include>
    <bar idref="fooid"/>
    <bar idref="fooid2"/>
</root>
martijn
  • 485
  • 2
  • 9
  • On the one hand, I am unable to get it right. First IntelliJ complained about the `http://www.w3.org/2001/03/xml.xsd` URI and now it does not accept the XSD [can you maybe post the full xsd/xml files?]. On the other hand, this seems fairly complicated to add the ids to transfer explicitly every time (in my real example, I have hundreds of them in file test1.xml). I saw the xpointer thing before and tried to include the root element only but that also did not work.. – Ronnie Marksch Jul 14 '21 at 07:18
  • I did not change the example code to much. All the changes are in my answer. So if you replace the original parts with mine it should work. I used Xmlspy to replicate the problem and there all files where valid. I understand that the xpointer thing is not going to work with more than 1 id that needs to be transferred. maybe you can restructure test1.xml so that you have another layer between root and foo and import from that id. this will mean you need to change your xml schema. – martijn Jul 14 '21 at 08:13
  • For the xml.xsd, I just downloaded the file and changed the URI from `http://www.w3.org/2001/03/xml.xsd` to the local version `xml.xsd`. The files `main.xsd` and `test1.xml` have no erros or sth but the `test2.xml` says that `XPointer resolution unsuccessful.` and that the two ids could therefore not be derived. I also managed now to use your previous shorter suggestion from above without the foolist but there the xpointer is also not resolved. I tried the xpointer `element(1/)` and then the Xinclude is resolved but then I am back with `Invalid id reference`. – Ronnie Marksch Jul 15 '21 at 11:06
  • have you tried to use the full path for the import. maybe it is not able to find the test1.xml file while importing it into your project. – martijn Jul 16 '21 at 04:47