Europass import: the SkillsPassport readers keep the HTML markup that the Candidate reader strips #563
Labels
No labels
accessibility
authentication
breaking change
bug
documentation
enhancement
interface
internationalisation
observability
performance
security
tier
1
tier
2
tier
3
tier/4
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
Postulo/postulo#563
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Found on 2026-09-29 in a read-only review of postulo at
95348908d, comparing the three Europass readers and running the SkillsPassport ones on a file with markup in it.Checked again on 2026-10-01 against
mainat0a5cad587: still present. The code is now atplugins/europass/reader.py:398(experience summary),:430(education highlights),:461-462(skill blocks) and:479(achievements), with the JSON equivalents at:681,:705,:736and:746._json_textis atreader.py:532-533,_plainatplugins/europass/candidate.py:245-262, and_textmoved toplugins/europass/common.py:146-157, the module both readers import since #248 and the place for_Wordsand_plainin the fix below.The Candidate reader passes every long field through
_plain(plugins/europass/candidate.py:244-261), which turns the editor's escaped HTML into lines of text, because "markup kept as it came would print on a CV as angle brackets". The SkillsPassport XML and JSON readers do not: they read the same kind of fields through_textand_json_text, which only collapse whitespace. Cedefop's editor wrote markup into these fields too; its own example file,europass-cl-cv-example-v3.3.0.xmlin theeuropass/rest-examples-javarepository, has escaped<br />in the work experienceActivities, the educationActivitiesand the communication skillsDescription. The module docstring promises that "a career arrives the same way from either" format.plugins/europass/reader.py:522(experience summary) and:554(education highlights),:585-586(skill blocks),:603(achievements); the JSON equivalents at:805,:829,:860and:870. The helpers are_text(reader.py:368-379) and_json_text(:656-657).tests/data/europass.xmlchanged so that anActivitiesholdsEvaluation of support measures<br />and young people,reader.read()returns the summaryEvaluation of support measures<br />and young people. With the Organisational skillsLabelholding an escaped<ul><li>Mentoring</li><li>Planning</li></ul>, the group comes back as one skill,'<ul><li>Mentoring</li><li>Planning</li></ul>', because_split_skillssplits only on newlines and semicolons. The JSON reader does the same with<p>…</p><ul><li>…</li></ul>inActivities. The same file read through the Candidate path would come back as plain lines._Wordsand_plainout ofcandidate.pyinto a small module of theeuropasspackage that both readers import, and apply_plainto the raw text of every SkillsPassport free-text field above, in the XML reader and the JSON reader, before_split_skillswhere a block is split. Keep the whitespace collapsing for short fields such as titles and names.Related to #318, which checks the Candidate reader against a real download and does not touch the SkillsPassport readers.
Done when
tests/test_europass.pyreads a SkillsPassport XML fixture and a JSON fixture whoseActivitiesand a skillsDescriptioncarry escaped<p>,<br />,<ul>and<li>, and asserts plain lines with no<in the summary, the highlights and each skill, and that a listed skill block splits into one skill per item.