xmlschema icon indicating copy to clipboard operation
xmlschema copied to clipboard

How to retrieve min/max occurence ? - wrong value reported by min_occurs/max_occurs

Open Thomasb81 opened this issue 8 months ago • 2 comments

Hello

Using following schema :

IPXACT/1685-2022/index.xsd or in a zip file ipxact_schema_files_20250213.zip

I would like yo retrieve cardinality of every element that can occurred in xml respecting the provided schema.

The execution of following script

import xmlschema

print(xmlschema.__version__)

schema = xmlschema.XMLSchema('../schema/2022/index.xsd')

addressBlock = schema.find("/ipxact:component/ipxact:memoryMaps/ipxact:memoryMap/ipxact:addressBlock")
print('min:',addressBlock.min_occurs)
print('max:',addressBlock.max_occurs)

result = schema.is_valid('test_xmlschema.xml')
print(result)

produces:

4.0.1
min: 1
max: 1
True

While I expect the print of addressBlock.min_occurs to produce 0 and addressBlock.max_occurs to produce None in order to represent the correct cardinality as described in the xs:group of upper level memoryMapGroup

memoryMap.xsd line 408:

	<xs:group name="memoryMap">
		<xs:annotation>
			<xs:documentation>A group elements for a memoryMap</xs:documentation>
		</xs:annotation>
		<xs:choice>
			<xs:element ref="ipxact:addressBlock"/>
			<xs:element ref="ipxact:bank"/>
			<xs:element ref="ipxact:subspaceMap"/>
		</xs:choice>
	</xs:group

memoryMap.xsd line 456:

        <xs:group name="memoryMapGroup">
		<xs:sequence>
			<xs:group ref="ipxact:memoryMap" minOccurs="0" maxOccurs="unbounded"/>
			<xs:element ref="ipxact:memoryRemap" minOccurs="0" maxOccurs="unbounded"/>
			<xs:element ref="ipxact:addressUnitBits" minOccurs="0"/>
			<xs:element name="shared" type="ipxact:sharedType" minOccurs="0">
				<xs:annotation>
					<xs:documentation>When the value is 'yes', the contents of the memoryMap are shared by all the references to this memoryMap, when the value is 'no' the contents of the memoryMap is not shared and when the value is 'undefined' (default) the sharing of the memoryMap is undefined.</xs:documentation>
				</xs:annotation>
			</xs:element>
		</xs:sequence>
	</xs:group>

The validation seems to not take into account the wrong value since the xmlschema is able to validate the attached document.

test_xmlschema.xml.zip

Thomasb81 avatar Apr 17 '25 01:04 Thomasb81

Hi, the validation counts the total occurs of the particles or nested groups of particles. In your case ipxact:addressBlock is part of a global group that has always minOccurs == maxOccurs == 1. The total max and min occurs during validation is calculated using a collections.Counter object, starting from the content type model group of the complex type.

I will check if has sense to add helper a pair of helper methods to calculate the total max and min occurs "statically", e.g.:

def get_max_occurs(self, group): ...
def get_min_occurs(self, group): ...

brunato avatar May 18 '25 17:05 brunato

Hi, in version v4.1.0 there are new helper functions for elements and type to get the total maximum/minimum occurs of a model particle:

    def overall_min_occurs(self, particle: ModelParticleType) -> int:
        """
        Returns the overall minimum for occurrences of a content model particle.
        The content type of the element must be 'element-only' or 'mixed'.
        """
        return self.type.overall_min_occurs(particle)

    def overall_max_occurs(self, particle: ModelParticleType) -> Optional[int]:
        """
        Returns the overall maximum for occurrences of a content model particle.
        The content type of the element must be 'element-only' or 'mixed'.
        """
        return self.type.overall_max_occurs(particle)

I hope those helpers could be what you need.

cheers

brunato avatar Jun 06 '25 06:06 brunato

Pretty confident that the new helper methods for XSD elements are useful for retrieving total min/max occurs. If not, reopen this issue. thanks

brunato avatar Oct 14 '25 09:10 brunato