Skip to content

Serialise a QTI item's language as xml:lang - #6099

Merged
AlexVelezLl merged 1 commit into
learningequality:unstablefrom
rtibblesbot:issue-6098-751e59
Aug 19, 2026
Merged

Serialise a QTI item's language as xml:lang#6099
AlexVelezLl merged 1 commit into
learningequality:unstablefrom
rtibblesbot:issue-6098-751e59

Conversation

@rtibblesbot

@rtibblesbot rtibblesbot commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

Summary

  • QTI 3.0 defines no language attribute; an item's language now serialises as xml:lang.

References

Fixes #6098. Read-side tolerance: #6095.

Reviewer guidance

  • The seven files under tests/utils/qti/fixtures/ are golden expected output compared verbatim by test_convert.py, not assertion-free tests. Mutating one attribute in each fails a distinct test_convert.py case.
  • The two exercise_file.checksum updates in test_exercise_creation.py follow from the attribute rename changing the zipped item bytes.
  • No data migration: consolidate() converts on read without persisting, so no stored raw_data carries language=.

AI usage

Used Claude Code to implement the change test-first from the plan on the issue. Verified with the full Python test suite and pre-commit.


@rtibblesbot's comments are generated by an LLM, and should be evaluated accordingly

How was this generated?
  • Ran pre-flight CI checks (lint, format, tests) and verified all pass
  • Rebased onto the target branch and resolved any conflicts
  • Reorganized commit history into clean, logical commits
  • Audited the diff to ensure only issue-relevant files are changed
  • Built PR body from the repository's PR template with evidence blocks

Deviations from the issue spec

Criterion Why not
Run the XSD's embedded Schematron rules in validate_qti_item Dropped at @AlexVelezLl's request. validation.py is untouched, so nothing here makes validation stricter, and the srcset-on-<img> sample fix it forced went with it. The cost: no regression guard on the root element's attribute names — the XSD's extensionAnyTypeLax.Attr wildcard admits language= as happily as xml:lang=.
@rtibblesbot

🟡 Waiting for feedback

Last updated: 2026-08-19 14:31 UTC

@AlexVelezLl AlexVelezLl left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After reviewing the implications of the schematron, I think it'd be better just not introduce it right now, so please drop that addition.

QTI 3.0 declares xml:lang on qti-assessment-item; `language` is not an
attribute of the element. Renaming the pydantic field to `xml__lang` is
enough — XMLElement.to_element already maps `__` to `:`.

Exercise zip checksums shift because the generated XML changed.
@rtibblesbot rtibblesbot changed the title Serialise a QTI item's language as xml:lang and run the item schema's Schematron rules Serialise a QTI item's language as xml:lang Aug 19, 2026
@rtibblesbot

Copy link
Copy Markdown
Contributor Author

After reviewing the implications of the schematron, I think it'd be better just not introduce it right now, so please drop that addition.

Dropped — the whole commit is off the branch (force-pushed), so validation.py and schema/README.md match unstable and the two Schematron tests are gone.

Searched for the rest of that commit's class rather than just the validator: grep -ri schematron|isoschematron over the branch is now 0 hits outside .plans/. The srcset<picture><source> fix in test_assessmentitem.py's sample item existed only because the Schematron rejected it, so it reverted too — Img permits srcset exactly as it did before this PR.

One line from that commit survives: test_validation.py's sample item builder now writes xml:lang=, not language=, matching what the serialiser emits. grep -rn 'language="' over contentcuration/ leaves two hits, both unrelated — db_tools.py (Django model) and test_convert.py (LegacyAssessmentItem, which keeps the field name).

Worth flagging: nothing now catches the root element's attribute names regressing — the XSD's extensionAnyTypeLax.Attr wildcard admits language= as readily as xml:lang=. PR title and body updated to stop claiming otherwise.

@AlexVelezLl AlexVelezLl left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code changes look good, tests provide good confidence.

@AlexVelezLl
AlexVelezLl merged commit 31c56ae into learningequality:unstable Aug 19, 2026
26 checks passed
@rtibblesbot
rtibblesbot deleted the issue-6098-751e59 branch August 19, 2026 18:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Legacy conversion writes the item language as language= instead of xml:lang, and validation cannot catch it

2 participants