diff --git a/crates/preflight/src/tests.rs b/crates/preflight/src/tests.rs index 07b92dee8a..8eea6afeb1 100644 --- a/crates/preflight/src/tests.rs +++ b/crates/preflight/src/tests.rs @@ -575,6 +575,9 @@ fn xmp_arrays_have_their_kind_and_item_types() { // Only white space around an array's items. assert_eq!(element("dc:creator", "strayA"), ["dc:creator"]); assert_eq!(element("dc:creator", "strayA"), ["dc:creator"]); + // rdf:parseType or rdf:resource on the property makes its value something other than the array. + assert_eq!(mistyped(r#">A"#), ["dc:creator"]); + assert_eq!(mistyped(r#">A"#), ["dc:creator"]); assert!(element("dc:creator", "\n \n A\n \n").is_empty()); // An rdf:resource element is empty. assert_eq!(mistyped(r#">x"#), ["dc:source"]); diff --git a/crates/preflight/src/xmp_types.rs b/crates/preflight/src/xmp_types.rs index 33b5d261d8..7ef694ba2f 100644 --- a/crates/preflight/src/xmp_types.rs +++ b/crates/preflight/src/xmp_types.rs @@ -616,8 +616,9 @@ fn field(fields: &[Field], ns: &str, name: &str) -> Option { fn array<'a, 'i>(e: &Node<'a, 'i>, children: &[Node<'a, 'i>], kind: &str) -> Option>> { match children { // Items are `rdf:li` (ISO 16684-1 7.9.2.4); any other element, or character data around - // them, breaks the array. - [a] if is(a, RDF, kind) && field_attributes(e).next().is_none() && blank(e) && blank(a) => { + // them, breaks the array, and so does `rdf:parseType` or `rdf:resource` on the property, + // which makes its value something else. + [a] if is(a, RDF, kind) && field_attributes(e).next().is_none() && blank(e) && blank(a) && !other_value_form(e) => { let items: Vec> = a.children().filter(Node::is_element).collect(); items.iter().all(|i| is(i, RDF, "li")).then_some(items) } @@ -639,6 +640,11 @@ fn structure<'a, 'i>(e: &Node<'a, 'i>, children: &[Node<'a, 'i>], resource: bool (children.is_empty() && empty && e.attribute((RDF, "resource")).is_none() && field_attributes(e).next().is_some()).then_some(*e) } +/// Whether `e` says its value is a resource or a literal of another kind, not the element it holds. +fn other_value_form(e: &Node<'_, '_>) -> bool { + e.attribute((RDF, "parseType")).is_some() || e.attribute((RDF, "resource")).is_some() +} + /// Whether `e` holds no character data but white space. fn blank(e: &Node<'_, '_>) -> bool { text(e).trim().is_empty()