M11: PDF/A verify takes no array from a property whose RDF attributes make its value something else (6.6.2.3.1)

An rdf:parseType or rdf:resource on a property element makes its value a
resource or another literal, not the rdf:Seq, rdf:Bag or rdf:Alt it holds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Pq7HyDBXygTf7jcqdsjcfn
This commit is contained in:
mtlcl410andClaude Opus 5.5 committed 2026-11-05 12:48:27 +08:00
1 parent c86b161672
commit 7bce37fefc
2 files changed
+11 -2

No files matched your search

+3
View File
@@ -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", "stray<rdf:Seq><rdf:li>A</rdf:li></rdf:Seq>"), ["dc:creator"]);
assert_eq!(element("dc:creator", "<rdf:Seq>stray<rdf:li>A</rdf:li></rdf:Seq>"), ["dc:creator"]);
// rdf:parseType or rdf:resource on the property makes its value something other than the array.
assert_eq!(mistyped(r#"><dc:creator rdf:parseType="Resource"><rdf:Seq><rdf:li>A</rdf:li></rdf:Seq></dc:creator>"#), ["dc:creator"]);
assert_eq!(mistyped(r#"><dc:creator rdf:resource="http://example.com/a"><rdf:Seq><rdf:li>A</rdf:li></rdf:Seq></dc:creator>"#), ["dc:creator"]);
assert!(element("dc:creator", "\n <rdf:Seq>\n <rdf:li>A</rdf:li>\n </rdf:Seq>\n").is_empty());
// An rdf:resource element is empty.
assert_eq!(mistyped(r#"><dc:source rdf:resource="http://example.com/a"><rdf:Seq><rdf:li>x</rdf:li></rdf:Seq></dc:source>"#), ["dc:source"]);
+8 -2
View File
@@ -616,8 +616,9 @@ fn field(fields: &[Field], ns: &str, name: &str) -> Option<Ty> {
fn array<'a, 'i>(e: &Node<'a, 'i>, children: &[Node<'a, 'i>], kind: &str) -> Option<Vec<Node<'a, 'i>>> {
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<Node<'a, 'i>> = 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()