Add <xref> element validations per SPS 1.10 specification#1136
Add <xref> element validations per SPS 1.10 specification#1136
Conversation
…pe values, bibr presence, rid-id correspondence, transcript xref, aff self-closing Co-authored-by: robertatakenaka <505143+robertatakenaka@users.noreply.github.com>
Rossi-Luciano
left a comment
There was a problem hiding this comment.
Evidência de revisão -- article_xref.py
Data: 2026-04-24
Revisor: Luciano
Artefatos analisados:
article_xref.py(validation) -- módulo de validação (ArticleXrefValidation)article_xref.py(model,models/v2/) --XMLCrossReference,Xref,Elementxref_rules.json-- parâmetros de configuraçãoarticle_xref.xml-- XML artificial gerado para cobertura de testesarticle_xref-2026-24-04-114300-errors.csv-- relatório de erros gerado pelo packtools
Metodologia
Análise cruzada entre os dois módulos de mesmo nome (article_xref.py de validation
e de models/v2), o JSON de regras, o XML artificial construído com o princípio do
defeito isolado, e o relatório CSV. Para cada caso documentado no XML verificou-se:
se o método de validação deveria disparar o erro (leitura do código), se o CSV contém
a entrada correspondente, se o nível de severidade está correto, e se casos válidos
estão corretamente ausentes do CSV. O model foi necessário para confirmar três pontos:
(1) distinção entre all_ids() e elems_by_id("*") usados em R5 e R6, (2) cálculo
de has_text_content para R10, e (3) como elems_by_id(attribs=[...]) filtra por
atributo para R8.
Regras validadas (10 métodos)
| # | Método | Nível configurado |
|---|---|---|
| R1 | validate_rid_presence |
CRITICAL |
| R2 | validate_ref_type_presence |
CRITICAL |
| R3 | validate_ref_type_value |
ERROR |
| R4 | validate_bibr_presence |
ERROR |
| R5 | validate_rid_has_corresponding_id |
ERROR |
| R6 | validate_xref_rid_has_corresponding_element_id |
ERROR |
| R7 | validate_element_id_has_corresponding_xref_rid |
ERROR |
| R8 | validate_attrib_name_and_value_has_corresponding_xref |
CRITICAL |
| R9 | validate_transcript_xref |
WARNING |
| R10 | validate_aff_self_closing |
INFO |
Casos de teste no XML artificial
| Caso | Defeito introduzido | Nível esperado | Isolamento |
|---|---|---|---|
| P1 | Nenhum -- caso ouro completo | OK (ausente do CSV) | aff1, f01, B01 com xrefs corretas |
| C-R1 | <xref ref-type="fig"> sem @Rid |
CRITICAL | R6 não dispara: elements_by_id[None] é não-vazio |
| C-R2 | <xref rid="B01"> sem @ref-type |
CRITICAL | rid="B01" existe; R5/R6 passam |
| C-R3 | <xref ref-type="invalid-type" rid="B01"> |
ERROR | rid="B01" existe; R5/R6 passam |
| C-R4* | não testável neste XML | ERROR | requer ausência total de xref ref-type="bibr" |
| C-R5/R6 | <xref ref-type="fig" rid="fig-inexistente"> |
ERROR + ERROR | ambas as regras disparam para a mesma xref (cascata esperada) |
| C-R7 | <fig id="f-orphan"> sem xref correspondente |
ERROR | nenhuma xref com rid="f-orphan" no documento |
| C-R8 + C-R9a | <sec sec-type="transcript" id="s-trans1"> sem xref algum |
CRITICAL + WARNING | cascata: R8 verifica existência de xref, R9 verifica ref-type="sec" |
| C-R9b | <sec sec-type="transcript" id="s-trans2"> + <xref ref-type="fn" rid="s-trans2"> |
WARNING | R8 PASS (xref existe); R9 WARNING (fn != sec) |
| C-R10 | <xref ref-type="aff" rid="aff1"></xref> (vazio) |
INFO | has_text_content=False; aff1 ainda tem xref com texto (P1) portanto R7 passa |
Verificação cruzada com o CSV
Todas as 10 entradas esperadas do módulo article_xref.py (validation) aparecem
no CSV sob o subject id and rid, com os níveis de severidade corretos:
| Linha CSV | Caso | Nível | Verificação |
|---|---|---|---|
| id and rid | C-R1 | CRITICAL | PASS -- "Provide a valid @Rid attribute for xref" |
| id and rid | C-R2 | CRITICAL | PASS -- "Provide a valid @ref-type attribute for xref" |
| id and rid | C-R3 | ERROR | PASS -- "Replace invalid-type with one of the allowed values" |
| id and rid | C-R5 | ERROR | PASS -- "@Rid=fig-inexistente has no corresponding @id in the document" |
| id and rid | C-R6 | ERROR | PASS -- "Found xref rid=fig-inexistente, but not found the corresponding fig" |
| id and rid | C-R7 | ERROR | PASS -- "Found fig id=f-orphan, but no corresponding xref was found" |
| id and rid | C-R8 | CRITICAL | PASS -- "Found sec sec-type=transcript id=s-trans1, but no corresponding xref" |
| id and rid | C-R9a | WARNING | PASS -- "Add xref ref-type=sec rid=s-trans1 to reference the transcript section" |
| id and rid | C-R9b | WARNING | PASS -- "Add xref ref-type=sec rid=s-trans2 to reference the transcript section" |
| id and rid | C-R10 | INFO | PASS -- "For ref-type=aff without text content, use self-closing" |
R4 (validate_bibr_presence) não aparece no CSV (is_valid=True; xref ref-type="bibr"
presente para B01). O caso ouro P1 não gera nenhuma entrada. Não foram identificados
falsos positivos nem falsos negativos originados do módulo.
Ruído identificado (outros módulos) -- 38 entradas
Ruído estrutural (XML artificial mínimo sem abstract, history, subject etc.):
abstract ausente, history dates ausentes (received, rev-request, rev-recd, accepted, pub),
subj-group heading ausente, disp-formula/inline-formula/table-wrap ausentes, app ausente,
open science statement ausente.
Ruído de ambiente: rendition PDF ausente, DOI não registrado no Crossref, issue não
verificada no Core.
Ruído da estrutura de afiliação (aff): a afiliação de teste é mínima (apenas institution
text); o validador de aff exige label, institution content-type original/orgname/orgdiv1,
country com código ISO, addr-line com state e city (9 entradas).
Ruído de contrib: o contrib no XML não tem <n> nem role, gerando 3x CRITICAL.
Novos tipos de ruído identificados nesta sessão (incorporados ao padrão):
<graphic xlink:href="...">: arquivos f01.jpg e f-orphan.jpg geram 2x CRITICAL
"file not present in package". Para próximos XMLs: omitir<graphic>ou omitir
o atributoxlink:href.<graphic>sem @id: 2x CRITICAL "Add id= to graphic". Adicionar @id a todos os
elementos graphic.<graphic>sem<alt-text>: 2x WARNING accessibility. Adicionar alt-text ou
omitir graphic.
Conclusão
O módulo article_xref.py (validation) está correto. Todas as 10 entradas
esperadas dispararam com os níveis de severidade corretos, sem falsos positivos nem
falsos negativos originados do módulo. R4 passou corretamente (bibr presente). A
regra R4 requer XML separado para teste do caso negativo (ausência total de bibr xrefs).
O que esse PR faz?
Implementa 7 das 10 regras de validação para o elemento
<xref>conforme SPS 1.10 e Critérios SciELO Brasil (70% de conformidade).P0 – Críticas:
validate_rid_presence(CRITICAL) —@ridobrigatório e não-vaziovalidate_ref_type_presence(CRITICAL) —@ref-typeobrigatório e não-vaziovalidate_ref_type_value(ERROR) —@ref-typedeve ser um dos 16 valores permitidosvalidate_bibr_presence(ERROR) — ao menos um<xref ref-type="bibr">no documentovalidate_rid_has_corresponding_id(ERROR) — todo@riddeve ter@idcorrespondenteP1 – Importantes:
validate_transcript_xref(WARNING) —<sec sec-type="transcript">precisa de<xref ref-type="sec">validate_aff_self_closing(INFO) —<xref ref-type="aff">sem texto deve usar formato self-closingCorrige bugs no método existente
validate_attrib_name_and_value_has_corresponding_xref()que usavaself.xref_xml(inexistente) e o builtinidem vez da variável do loop.Onde a revisão poderia começar?
packtools/sps/validation/article_xref.py— contém todas as novas validações e as correções nos métodos existentes.Como este poderia ser testado manualmente?
74 testes unitários:
python -m pytest tests/sps/validation/test_article_xref.py -vAlgum cenário de contexto que queira dar?
Validações parciais para
<xref>já existiam (validate_xref_rid_has_corresponding_element_id,validate_element_id_has_corresponding_xref_rid,validate_attrib_name_and_value_has_corresponding_xref). Este PR complementa com as regras faltantes e corrige bugs nos métodos existentes. Os testes existentes foram reescritos para o formato atual com suporte a i18n (msg_text,msg_params,adv_text,adv_params).Arquivos alterados:
packtools/sps/validation_rules/xref_rules.json— novo arquivo de configuração de regraspacktools/sps/models/v2/article_xref.py—all_xrefs(),all_ids(),transcript_sections()emXMLCrossReferencepacktools/sps/validation/article_xref.py— 7 novos métodos + correção de bugspacktools/sps/validation/xml_validations.py— orquestrador atualizadotests/sps/validation/test_article_xref.py— 74 testes em 14 classesScreenshots
N/A
Quais são tickets relevantes?
Referências
<xref>: Referência Cruzada<xref>Warning
Firewall rules blocked me from connecting to one or more addresses (expand for details)
I tried to connect to the following addresses, but was blocked by firewall rules:
api.crossref.org/usr/bin/python python -m pytest tests/sps/validation/ -v --ignore=tests/sps/validation/test_footnotes.py(dns block)If you need me to access, download, or install something from one of these locations, you can either:
Original prompt
This section details on the original issue you should resolve
<issue_title>Criar validações para o elemento </issue_title>
<issue_description>## Objetivo
Implementar validações para o elemento
<xref>conforme a especificação SPS 1.10 e Critérios SciELO Brasil, aumentando a conformidade de X% para 70% (7 de 10 regras).Nota: Algumas validações para
<xref>podem já estar parcialmente implementadas no repositório. Este Issue visa reavaliar, complementar e garantir cobertura completa das regras SPS 1.10 e Critérios SciELO Brasil.Contexto
O elemento
<xref>é usado para referência cruzada relacionando informações no texto. Para SciELO Brasil, é obrigatória a presença de pelo menos uma<xref>com@ref-type="bibr"(referência bibliográfica) no documento. Validações corretas garantem presença de atributos obrigatórios, valores válidos, e correspondência entre@ride@id.Conformidade atual: X de 10 regras implementadas (X%)
Meta após implementação: 7 de 10 regras (70%)
Documentação SPS
Referência oficial: https://docs.google.com/document/d/1GTv4Inc2LS_AXY-ToHT3HmO66UT0VAHWJNOIqzBNSgA/edit?tab=t.0#heading=h.xref
Regras principais conforme SPS 1.10 e Critérios SciELO Brasil:
Ocorrência:
<xref>pode aparecer zero ou mais vezes em:<article-title>,<attrib>,<contrib>,<p>,<td>,<th>,<trans-title>,<sec>,<verse-line>Obrigatoriedade (Critério SciELO Brasil):
<xref>com@ref-type="bibr"deve ocorrer pelo menos uma vez no documentoAtributos obrigatórios:
@rid- Contém identificador do elemento referenciado (obrigatório)@ref-type- Especifica tipo de referência cruzada (obrigatório)Valores permitidos para
@ref-type:aff- Afiliaçãoapp- Apêndiceauthor-notes- Notas relacionadas ao autorbibr- Referência bibliográficabio- Bibliografia do autorboxed-text- Caixa de textocontrib- Autoriacorresp- Autor correspondentedisp-formula- Fórmula/Equaçãofig- Figura ou grupo de figurasfn- Notalist- Lista ou item da listasec- Seçãosupplementary-material- Material suplementartable- Tabela ou grupo de tabelastable-fn- Nota de rodapé de tabelasCorrespondência
@ride@id:@ridobrigatoriamente deve ter@idcorrespondente no XML@idpode ou não ter@ridcorrespondenteRegra especial para transcrição:
<xref ref-type="sec" @rid>é obrigatório quando existe<sec sec-type="transcript">Regra especial para afiliação:
<xref ref-type="aff" rid="aff1"/>(self-closing)Regra de
<sup>:<sup>não pode abarcar<xref>quando não há caracteres textuais<sup>deve estar dentro de<xref>Menção obrigatória:
aff, deve ocorrer menção ou etiqueta correspondente no textoRegras a Implementar
P0 – Críticas (implementar obrigatoriamente)
@rid@ridé obrigatório em<xref>@ref-type@ref-typeé obrigatório em<xref>@ref-type@ref-typedeve estar na lista de valores permitidos@ref-type="bibr"<xref>com@ref-type="bibr"(Critério SciELO Brasil)@ride@id@ridem<xref>deve ter@idcorrespondente no documentoP1 – Importantes (implementar se possível)
<xref>para transcrição<sec sec-type="transcript">, deve haver<xref ref-type="sec">referenciando-a@ref-type="aff"sem conteúdo textual, recomenda-se usar elemento self-closing<xref ... />P2 – Futuras (fora do escopo deste Issue)
<sup>não abarca<xref>sem textoArquivos a Criar/Modificar
Avaliar existentes (podem ter validações parciais):
packtools/sps/models/xref.pyou similar – Verificar se modelo existepacktools/sps/validation/xref.py– Verificar validações existentes📍 Connect Copilot coding agent with Jira, Azure Boards or Linear to delegate work to Copilot in one click without leaving your project management tool.