-->

Value of XML element depends on values of other el

2019-07-10 23:05发布

问题:

As example, let's say that orange GMC trucks are worth $20,000 while white and black GMC trucks are worth $10,000.

Given the following XML:

<example>
    <car>
        <make value='GMC'/>
        <model value='Truck'/>
        <configuration>
            <color value="orange"/>
            <bed value="short"/>
            <cab value="regular"/>
        </configuration>
        <price value='10000'/>
    </car>
</example>

The XML is telling me that my sales staff is selling an orange GMC short-bed truck with a regular cab for $10,000. I want to use a schema to prevent my staff from selling the truck for less than $20,000.

Can I create an XSD file to enforce the restriction that the car must be a GMC, a truck, orange, and priced at $20,000. In other words can I base a restriction on the values of four separate elements?

The example XML would fail to validate because the price is less than $20,000 or because the color is orange instead of white or black. Depends on how you want to look at it.

Update

According to http://www.ibm.com/developerworks/library/x-xml11pt2/

Unfortunately, XML Schema 1.0 did not provide a way to enforce these rules. To implement such constraints, you would

  • Write code at the application level (after XML schema validation)
  • Use stylesheet checking (also a post-validation process)
  • Use a different XML schema language such as RelaxNG or Schematron

With the constant requests for co-occurrence constraint checking support from the XML Schema 1.0 user community, the XML Schema 1.1 working group introduced the concept of assertions and type alternatives in XML Schema 1.1 to allow XML schema authors to express such constraints.

OK, so looking at my current environment I'm using lxml which does not support XSD 1.1. So, I will have to use Schematron or RelaxNG.

回答1:

XSD 1.0

Your constraints cannot be expressed in XSD 1.0.

XSD 1.1

Your constraints can be expressed using assertions in XSD 1.1:

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
           elementFormDefault="qualified"
           xmlns:vc="http://www.w3.org/2007/XMLSchema-versioning" 
           vc:minVersion="1.1">
  <xs:element name="example">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="car">
          <xs:complexType>
            <xs:sequence>
              <xs:element name="make" type="valAttrType"/>
              <xs:element name="model" type="valAttrType"/>
              <xs:element name="configuration">
                <xs:complexType>
                  <xs:sequence>
                    <xs:element name="color" type="valAttrType"/>
                    <xs:element name="bed" type="valAttrType"/>
                    <xs:element name="cab" type="valAttrType"/>
                  </xs:sequence>
                </xs:complexType>
              </xs:element>
              <xs:element name="price" type="valAttrType"/>
            </xs:sequence>
            <xs:assert test="not(    make/@value='GMC' 
                                 and model/@value='Truck' 
                                 and configuration/color/@value='orange')
                              or number(price/@value)=20000"/>
            <xs:assert test="not(    make/@value='GMC' 
                                 and model/@value='Truck' 
                                 and configuration/color/@value='black')
                              or number(price/@value)=10000"/>
          </xs:complexType>
        </xs:element>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
  <xs:complexType name="valAttrType">
    <xs:attribute name="value" type="xs:string"/>
  </xs:complexType>
</xs:schema>