Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Key/keyref not performed on dynamic types #245

Closed
robbert-harms opened this issue Apr 28, 2021 · 4 comments
Closed

Key/keyref not performed on dynamic types #245

robbert-harms opened this issue Apr 28, 2021 · 4 comments

Comments

@robbert-harms
Copy link

Hi brunato,

I was trying to add a key/keyref to one of my nodes with a dynamic type, but unfortunately it won't catch incorrect values. I made a small demo case:

XSD:

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:vc="http://www.w3.org/2007/XMLSchema-versioning" elementFormDefault="qualified"
    attributeFormDefault="unqualified" vc:minVersion="1.1"
    targetNamespace="http://www.test.com/XMLSchema/data/2021"
    xmlns="http://www.test.com/XMLSchema/data/2021"
    xmlns:ad="http://www.test.com/XMLSchema/data/2021">
    <xs:element name="assessment">
        <xs:annotation>
            <xs:documentation>Data about the performed tests.</xs:documentation>
        </xs:annotation>
        <xs:complexType>
            <xs:sequence>
                <xs:element maxOccurs="unbounded" minOccurs="0" name="part" type="AssessmentPart">
                    <xs:key name="circle_id_key">
                        <xs:annotation>
                            <xs:documentation>For ContrastVisionTest. 

Since all parts are types we can not add keys and keyrefs to them. As such, we add the constraints here.</xs:documentation>
                        </xs:annotation>
                        <xs:selector xpath="ad:screen_elements/ad:contrast_circles/ad:circle"/>
                        <xs:field xpath="@circle_id"/>
                    </xs:key>
                    <xs:keyref name="circle_id_keyref" refer="circle_id_key">
                        <xs:selector xpath="ad:events/ad:circle_pressed"/>
                        <xs:field xpath="@circle_id"/>
                    </xs:keyref>
                </xs:element>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
    <xs:complexType abstract="true" name="AssessmentPart">
        <xs:annotation>
            <xs:documentation>Base type for the assessment element.</xs:documentation>
        </xs:annotation>
    </xs:complexType>
    <xs:complexType abstract="true" name="AssessmentTest">
        <xs:annotation>
            <xs:documentation>Base type for a test.</xs:documentation>
        </xs:annotation>
        <xs:complexContent>
            <xs:extension base="AssessmentPart"/>
        </xs:complexContent>
    </xs:complexType>
    <xs:complexType name="ContrastVisionTest">
        <xs:complexContent>
            <xs:extension base="AssessmentTest">
                <xs:sequence>
                    <xs:element name="screen_elements">
                        <xs:complexType>
                            <xs:sequence>
                                <xs:element name="contrast_circles">
                                    <xs:complexType>
                                        <xs:sequence>
                                            <xs:element maxOccurs="3" name="circle" minOccurs="3">
                                                <xs:complexType>
                                                  <xs:attribute name="circle_id" use="required">
                                                  <xs:annotation>
                                                  <xs:documentation>The id of this circle, used to reference the circle presses.</xs:documentation>
                                                  </xs:annotation>
                                                  <xs:simpleType>
                                                  <xs:restriction base="xs:integer">
                                                  <xs:minInclusive value="0"/>
                                                  <xs:maxInclusive value="9"/>
                                                  </xs:restriction>
                                                  </xs:simpleType>
                                                  </xs:attribute>
                                                </xs:complexType>
                                            </xs:element>
                                        </xs:sequence>
                                    </xs:complexType>
                                </xs:element>
                            </xs:sequence>
                        </xs:complexType>
                    </xs:element>
                    <xs:element name="events">
                        <xs:complexType>
                            <xs:sequence>
                                <xs:element maxOccurs="unbounded" minOccurs="0"
                                    name="circle_pressed">
                                    <xs:complexType>
                                        <xs:attribute name="circle_id" type="xs:integer"
                                            use="required"/>
                                    </xs:complexType>
                                </xs:element>
                            </xs:sequence>
                        </xs:complexType>
                    </xs:element>
                </xs:sequence>
            </xs:extension>
        </xs:complexContent>
    </xs:complexType>
</xs:schema>

XML:

<?xml version="1.0" encoding="UTF-8"?>
<assessment xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns:vc="http://www.w3.org/2007/XMLSchema-versioning"
 xmlns="http://www.test.com/XMLSchema/data/2021"
 xsi:schemaLocation="http://www.test.com/XMLSchema/data/2021">
    <part xsi:type="ContrastVisionTest">
        <screen_elements>
            <contrast_circles>
                <circle circle_id="1"/>
                <circle circle_id="1"/>
                <circle circle_id="2"/>
            </contrast_circles>
        </screen_elements>
        <events>
            <circle_pressed circle_id="0"/>
            <circle_pressed circle_id="1"/>
            <circle_pressed circle_id="2"/>
        </events>
    </part>
</assessment>

Other validation libraries, such as Xerex throw a warning that circle_id is not unique, i.e. that I use circle_id="1" twice.

The XMLSchema library in general works for validating key/keyref, but it seems to fail with elements referencing an xsi:type, such as in the above example.

Is this something that can be fixed?

Thank you for making this library, it helps me a lot in moving fully to Python.

Best,

Robbert

@brunato
Copy link
Member

brunato commented Apr 30, 2021

Hi,
each key identity has a dictionary with schema's elements related to its XPath selector, so the fix is to add the missing XSD elements when a dynamic type is used. For doing this I've added a dummy element for XPath operations and a part inside the "xsi:type" block of XsdElement.iter_decode().

        if XSI_TYPE in elem.attrib:
            type_name = elem.attrib[XSI_TYPE].strip()
            try:
                xsd_type = self.maps.get_instance_type(type_name, xsd_type, namespaces)
            except (KeyError, TypeError) as err:
                yield self.validation_error(validation, err, elem, **kwargs)
            else:
                # Add missing selected elements to identity
                if self.identities:
                    xpath_element = XPathElement(self.name, xsd_type)
                    for identity in self.identities.values():
                        context = IdentityXPathContext(self.schema, item=xpath_element)
                        for e in identity.selector.token.select_results(context):
                            if e not in identity.elements:
                                identity.elements[e] = None

The fix will be available in the next release.

Thank you for providing clear samples for the case (I will add them into package's tests).

@robbert-harms
Copy link
Author

Hi Brunato,

Thank you for your looking into the matter. Glad my examples are of help.

Looking forward to the next release.

Best wishes,

Robbert

brunato added a commit that referenced this issue May 3, 2021
  - Add a dummy XPathElement for XPath operations on dynamic types
  - Add regression test for issue #243 (XPath processor fault)
@brunato
Copy link
Member

brunato commented May 3, 2021

Hi @robbert-harms,
a new release of xmlschema is available (v1.6.2). If you upgrade also elementpath is updated to the latest (for fixing issue #243).

Best regards,
Davide

@robbert-harms
Copy link
Author

Thank you Davide, for repairing this so swiftly.

Your fixed for this worked as well.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants