///|
fn referenced_prefixes(text : String, names : Map[String?, Bool]) -> Unit {
let mut token = StringBuilder()
for ch in text {
if ch == ':' {
let prefix = token.to_string()
let valid = try {
valid_local_name(prefix)
true
} catch {
_ => false
}
if valid {
names[Some(prefix)] = true
}
token = StringBuilder()
} else if xml_name_char(ch.to_int()) {
token.write_char(ch)
} else {
token = StringBuilder()
}
}
}
///|
/// Namespace declarations themselves are not data, but prefixes occurring in opaque values
/// retain their bindings. This is deliberately conservative without claiming XSD validation.
fn namespace_references(
attributes : Array[XmlAttributeValue],
content : Array[XmlValue],
) -> Map[String?, Bool] {
let names : Map[String?, Bool] = Map([])
for attribute in attributes {
referenced_prefixes(attribute.value, names)
if attribute.namespace_uri ==
Some("http://www.w3.org/2001/XMLSchema-instance") &&
attribute.name == "type" &&
!attribute.value.contains(":") {
names[None] = true
}
}
for value in content {
if value is Text(text) {
referenced_prefixes(text, names)
}
}
names
}
///|
fn namespace_context_equal(
left : Array[NamespaceBinding],
right : Array[NamespaceBinding],
attributes : Array[XmlAttributeValue],
content : Array[XmlValue],
) -> Bool {
let names = namespace_references(attributes, content)
for (prefix, _) in names {
let left_uri = namespace_uri_for(left, prefix).unwrap_or("")
let right_uri = namespace_uri_for(right, prefix).unwrap_or("")
if left_uri != right_uri {
return false
}
}
true
}
///|
fn value_namespace_content(value : DataValue?) -> Array[XmlValue] {
match value {
Some(ScalarValue(TextValue(text))) => [Text(text)]
Some(XmlPayload(content)) => content
_ => []
}
}
///|
fn default_context_equal(left : Key, right : Key) -> Bool {
namespace_context_equal(
left.default_namespaces,
right.default_namespaces,
left.default_extra,
value_namespace_content(left.default_value),
)
}