如何在XSD中定义fsinfo元素的两种属性语法并实现校验?
Got it, let's tackle this XSD problem step by step. Here's how you can meet all three requirements while keeping your existing XML files fully compatible:
1. Merge Both Attribute Grammars with Mutually Exclusive Validation
We'll leverage XSD 1.1 assertions (since XSD 1.0 can't handle conditional attribute constraints cleanly) to enforce two valid, non-overlapping scenarios for the fsinfo element:
- Scenario 1: Only
lineandcommentattributes are present - Scenario 2: All required full-set attributes (
real_dev,mp,fs,dump,pass) are present, plus any optional attributes from the full grammar
First, define reusable attribute groups to keep the XSD organized:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" version="1.1"> <!-- Attribute group for the simplified fsinfo variant --> <xs:attributeGroup name="fsinfo-simplified"> <xs:attribute name="line" type="xs:string" use="required"/> <xs:attribute name="comment" type="xs:string" use="optional"/> </xs:attributeGroup> <!-- Attribute group for the full fsinfo variant --> <xs:attributeGroup name="fsinfo-full"> <xs:attribute name="line" type="xs:string" use="optional"/> <xs:attribute name="real_dev" type="xs:string" use="required"/> <xs:attribute name="mount_dev" type="xs:string" use="optional"/> <xs:attribute name="mp" type="xs:string" use="required"/> <xs:attribute name="fs" type="xs:string" use="required"/> <xs:attribute name="mkfs_opts" type="xs:string" use="optional"/> <xs:attribute name="options" type="xs:string" use="optional" default="defaults"/> <xs:attribute name="dump" type="xs:string" use="required"/> <xs:attribute name="pass" type="xs:string" use="required"/> <xs:attribute name="format" type="xs:string" use="optional"/> <xs:attribute name="comment" type="xs:string" use="optional"/> </xs:attributeGroup> <!-- Define the fsinfo element with validation rules --> <xs:element name="fsinfo"> <xs:complexType> <xs:choice> <xs:attributeGroup ref="fsinfo-simplified"/> <xs:attributeGroup ref="fsinfo-full"/> </xs:choice> <!-- Rule 1: Block empty fsinfo tags --> <xs:assert test="count(@*) > 0"/> <!-- Rule 2: Ensure mutual exclusivity and full required attributes when using the full grammar --> <xs:assert test=" (exists(@line) and not(exists(@real_dev)) and not(exists(@mp)) and not(exists(@fs)) and not(exists(@dump)) and not(exists(@pass))) or (exists(@real_dev) and exists(@mp) and exists(@fs) and exists(@dump) and exists(@pass)) "/> </xs:complexType> </xs:element> </xs:schema>
Key Notes:
- The
<xs:choice>lets the element use either attribute group, but the assertion prevents mixing attributes between groups (e.g., you can't haveline+real_devwithout all other required full attributes). - The
optionsattribute has its default set todefaultsas specified.
2. Block Empty fsinfo Tags
The first <xs:assert test="count(@*) > 0"/> ensures the fsinfo element has at least one attribute, so empty <fsinfo/> tags will fail validation immediately.
3. Allow Arbitrary Attribute Order
Good news—XSD doesn't enforce attribute order by default. All attributes defined in the complex type can appear in any order, so this requirement is already covered without extra work.
Validating with xmlstarlet
Since we're using XSD 1.1 features, you need to include the --xsd11 flag when running the validation command:
# Validate your XML file against the updated XSD xmlstarlet val --xsd11 your-schema.xsd your-xml-file.xml
Example Valid XMLs:
- Simplified variant:
<fsinfo line="5" comment="Temporary mount point placeholder"/> - Full variant (with optional attributes):
<fsinfo mp="/home" fs="xfs" real_dev="/dev/sdb1" dump="0" pass="2" options="rw,noatime" comment="Home filesystem"/>
Example Invalid XMLs:
- Empty tag:
<fsinfo/>(fails the non-empty assertion) - Mixed incomplete attributes:
<fsinfo line="3" real_dev="/dev/sda1"/>(fails the mutual exclusivity assertion) - Missing required full attribute:
<fsinfo real_dev="/dev/sda1" mp="/" fs="ext4" dump="0"/>(fails the full-set required attribute check)
内容的提问来源于stack exchange,提问作者Olivier LAHAYE

