An identity-constraint (unique/key/keyref) field that selects an absent attribute or an empty element whose declaration carries a default or fixed value now takes that value as its identity-tuple component, so two members can collide on the defaulted value (idG011/idG012 default, idF016/idF017 fixed) where the duplicate was previously missed. The default/fixed value constraints on identity-field targets are gathered at compile time (identityFieldConstraints, mirroring identityFieldTypes) and threaded through to the identity validator. The substitution is exact about absent versus present-empty: an @attr field is defaulted only when the attribute is ABSENT (an empty node-set), never when present with value ""; a "." element field only when the selected element has no character content. Applying a default only adds an identity value where the schema declares one, so it can create a genuine duplicate-key detection but never reject a valid instance. To keep within the file/type-size and one-type-per-file limits, FieldValue, XPathQueryCache, and the schema-location hints were extracted to their own files (behavior-preserving moves). invalid-instances-accepted 50 to 45, no false positive (valid-instances-rejected and valid-schemas-rejected held at 0), no other bucket moved. An adversarial review probed present-empty attributes, element content winning over a default, fixed values, keyref matching, multi-field keys, and merged-schema defaults, and found no over-rejection.
31 lines
1.3 KiB
Swift
31 lines
1.3 KiB
Swift
extension PureXML.Schema.Document {
|
|
/// The schema-document locations an instance points at through
|
|
/// `xsi:schemaLocation` (the second token of each namespace/location pair)
|
|
/// and `xsi:noNamespaceSchemaLocation` (a single location).
|
|
static func hintedSchemaLocations(in node: PureXML.Model.Node) -> [String] {
|
|
guard case let .document(children) = node, let root = children.compactMap(\.element).first else {
|
|
return []
|
|
}
|
|
var locations: [String] = []
|
|
for attribute in root.attributes {
|
|
let isInstance = attribute.name.namespaceURI == "http://www.w3.org/2001/XMLSchema-instance"
|
|
|| attribute.name.prefix == "xsi"
|
|
guard isInstance else { continue }
|
|
switch attribute.name.localName {
|
|
case "schemaLocation":
|
|
let tokens = attribute.value.split(whereSeparator: \.isWhitespace).map(String.init)
|
|
var index = 1
|
|
while index < tokens.count {
|
|
locations.append(tokens[index])
|
|
index += 2
|
|
}
|
|
case "noNamespaceSchemaLocation":
|
|
locations.append(attribute.value)
|
|
default:
|
|
break
|
|
}
|
|
}
|
|
return locations
|
|
}
|
|
}
|