Objetivo
Implementar validações para os elementos <sub-article> e <front-stub> 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 <sub-article> e <front-stub> 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 <sub-article> indica um documento aninhado dentro de outro e é obrigatório para documentos traduzidos. Sub-artigos herdam metadados do documento pai, necessitando apenas do elemento <front-stub> sem <journal-meta> e <article-meta>. Validações corretas garantem presença de atributos obrigatórios, estrutura adequada de <front-stub>, e conformidade com requisitos de tradução.
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.subarticle
Regras principais conforme SPS 1.10 e Critérios SciELO Brasil:
-
Ocorrência:
<sub-article> pode aparecer zero ou mais vezes em <article> e <sub-article>
-
Uso obrigatório:
- Obrigatório para documentos traduzidos
-
Atributos obrigatórios em <sub-article>:
@article-type (obrigatório)
@id (obrigatório)
@xml:lang (obrigatório)
-
Valores permitidos para @article-type:
translation - Tradução (obrigatório para documentos traduzidos)
reviewer-report - Parecer (revisão por pares)
article-commentary - Comentário
letter - Carta
reply - Resposta
-
Elemento <front-stub> obrigatório:
<sub-article> deve conter <front-stub>
- Proibido:
<journal-meta> e <article-meta> (herdam do pai)
-
Elementos obrigatórios em <front-stub>:
<contrib-group> (obrigatório)
<article-title> (obrigatório)
-
Regra de PDF:
@article-type="translation": um PDF para cada idioma
- Outros tipos: mesmo PDF, sem DOI próprio
-
Regras específicas para translation:
- Traduções devem ser enviadas junto com versão no idioma original
- PMC/PubMed: inglês em
<article>, outras traduções em <sub-article>
- Incluir dados traduzidos: afiliação, resumo, palavras-chave, notas de autor
- Afiliação não traduzida: usar
<institution content-type="original">
<elocation-id>, DOI, <history>: só se diferentes do original
-
Unicidade:
- Cada
<sub-article> deve ter @id único
Regras a Implementar
P0 – Críticas (implementar obrigatoriamente)
| # |
Regra |
Nível |
Descrição |
| 1 |
Validar presença de @article-type |
CRITICAL |
O atributo @article-type é obrigatório em <sub-article> |
| 2 |
Validar presença de @id |
CRITICAL |
O atributo @id é obrigatório em <sub-article> |
| 3 |
Validar presença de @xml:lang |
CRITICAL |
O atributo @xml:lang é obrigatório em <sub-article> |
| 4 |
Validar valores permitidos de @article-type |
ERROR |
O valor de @article-type deve estar na lista de valores permitidos |
| 5 |
Validar presença de <front-stub> |
CRITICAL |
O elemento <front-stub> é obrigatório em <sub-article> |
| 6 |
Validar presença de <contrib-group> em <front-stub> |
CRITICAL |
O elemento <contrib-group> é obrigatório em <front-stub> |
| 7 |
Validar presença de <article-title> em <front-stub> |
CRITICAL |
O elemento <article-title> é obrigatório em <front-stub> |
P1 – Importantes (implementar se possível)
| # |
Regra |
Nível |
Descrição |
| 8 |
Validar ausência de <journal-meta> em <front-stub> |
ERROR |
O elemento <journal-meta> não deve aparecer em <front-stub> (metadados são herdados do documento pai) |
| 9 |
Validar ausência de <article-meta> em <front-stub> |
ERROR |
O elemento <article-meta> não deve aparecer em <front-stub> (metadados são herdados do documento pai) |
| 10 |
Validar unicidade de @id |
ERROR |
Cada <sub-article> deve ter um @id único |
P2 – Futuras (fora do escopo deste Issue)
| # |
Regra |
Motivo de exclusão |
| 11 |
Validar que para PMC/PubMed inglês está em <article> |
Alta complexidade - requer contexto de indexação externa |
| 12 |
Validar consistência de idioma entre @xml:lang e <article-categories> |
Média complexidade - requer análise cross-element |
| 13 |
Validar que <elocation-id>, DOI, <history> só aparecem se diferentes do original |
Alta complexidade - requer comparação com documento pai |
| 14 |
Validar presença de artigo original quando há translation |
Alta complexidade - requer análise de estrutura completa |
Arquivos a Criar/Modificar
Avaliar existentes (podem ter validações parciais):
packtools/sps/models/sub_article.py ou similar – Verificar se modelo existe
packtools/sps/validation/sub_article.py – Verificar validações existentes
packtools/sps/validation/rules/sub_article_rules.json ou similar – Verificar configuração
Criar (se não existirem):
packtools/sps/models/sub_article.py – Modelo de extração de dados
packtools/sps/validation/sub_article.py – Validações
packtools/sps/validation/rules/sub_article_rules.json – Configuração de níveis de erro
tests/sps/validation/test_sub_article.py – Testes unitários
Referenciar (implementações similares):
packtools/sps/validation/article_and_subarticles.py – Validação de article já existe
packtools/sps/validation/utils.py – Funções auxiliares (build_response)
Exemplos de XML
XML Válido (deve passar sem erros):
<!-- Exemplo 1: Tradução completa para português -->
<article article-type="research-article" xml:lang="en">
<front>
<journal-meta>
<!-- metadados do periódico -->
</journal-meta>
<article-meta>
<article-id pub-id-type="doi">10.1590/example</article-id>
<title-group>
<article-title>Technology transfer during the covid-19 pandemic</article-title>
</title-group>
<contrib-group>
<contrib contrib-type="author">
<name>
<surname>Carneiro</surname>
<given-names>Tainá Ferreira</given-names>
</name>
</contrib>
</contrib-group>
<abstract>
<p>English abstract.</p>
</abstract>
</article-meta>
</front>
<body>
<p>English content.</p>
</body>
<sub-article article-type="translation" id="S1" xml:lang="pt">
<front-stub>
<title-group>
<article-title>Transferência tecnológica durante a pandemia de covid-19</article-title>
</title-group>
<contrib-group>
<contrib contrib-type="author">
<name>
<surname>Carneiro</surname>
<given-names>Tainá Ferreira</given-names>
</name>
</contrib>
</contrib-group>
<abstract>
<p>Resumo em português.</p>
</abstract>
</front-stub>
<body>
<p>Conteúdo em português.</p>
</body>
</sub-article>
</article>
<!-- Exemplo 2: Parecer (reviewer-report) -->
<article article-type="research-article" xml:lang="en">
<front>
<!-- metadados -->
</front>
<body>
<!-- conteúdo do artigo -->
</body>
<sub-article article-type="reviewer-report" id="R1" xml:lang="en">
<front-stub>
<title-group>
<article-title>Reviewer Report</article-title>
</title-group>
<contrib-group>
<contrib contrib-type="author">
<name>
<surname>Smith</surname>
<given-names>John</given-names>
</name>
</contrib>
</contrib-group>
</front-stub>
<body>
<p>Review content.</p>
</body>
</sub-article>
</article>
<!-- Exemplo 3: Comentário (article-commentary) -->
<article article-type="research-article" xml:lang="en">
<front>
<!-- metadados -->
</front>
<body>
<!-- conteúdo -->
</body>
<sub-article article-type="article-commentary" id="C1" xml:lang="en">
<front-stub>
<title-group>
<article-title>Commentary on this article</article-title>
</title-group>
<contrib-group>
<contrib contrib-type="author">
<name>
<surname>Jones</surname>
<given-names>Mary</given-names>
</name>
</contrib>
</contrib-group>
</front-stub>
<body>
<p>Commentary content.</p>
</body>
</sub-article>
</article>
<!-- Exemplo 4: Carta (letter) -->
<article article-type="research-article" xml:lang="en">
<front>
<!-- metadados -->
</front>
<body>
<!-- conteúdo -->
</body>
<sub-article article-type="letter" id="L1" xml:lang="en">
<front-stub>
<title-group>
<article-title>Letter regarding this article</article-title>
</title-group>
<contrib-group>
<contrib contrib-type="author">
<name>
<surname>Brown</surname>
<given-names>Robert</given-names>
</name>
</contrib>
</contrib-group>
</front-stub>
<body>
<p>Letter content.</p>
</body>
</sub-article>
</article>
<!-- Exemplo 5: Resposta (reply) -->
<article article-type="letter" xml:lang="en">
<front>
<!-- metadados da carta -->
</front>
<body>
<!-- conteúdo da carta -->
</body>
<sub-article article-type="reply" id="R1" xml:lang="en">
<front-stub>
<title-group>
<article-title>Reply to the letter</article-title>
</title-group>
<contrib-group>
<contrib contrib-type="author">
<name>
<surname>Author</surname>
<given-names>Original</given-names>
</name>
</contrib>
</contrib-group>
</front-stub>
<body>
<p>Reply content.</p>
</body>
</sub-article>
</article>
<!-- Exemplo 6: Múltiplas traduções -->
<article article-type="research-article" xml:lang="en">
<front>
<!-- metadados -->
</front>
<body>
<!-- conteúdo em inglês -->
</body>
<sub-article article-type="translation" id="S1" xml:lang="pt">
<front-stub>
<title-group>
<article-title>Título em português</article-title>
</title-group>
<contrib-group>
<contrib contrib-type="author">
<name>
<surname>Silva</surname>
<given-names>João</given-names>
</name>
</contrib>
</contrib-group>
</front-stub>
<body>
<p>Conteúdo em português.</p>
</body>
</sub-article>
<sub-article article-type="translation" id="S2" xml:lang="es">
<front-stub>
<title-group>
<article-title>Título en español</article-title>
</title-group>
<contrib-group>
<contrib contrib-type="author">
<name>
<surname>García</surname>
<given-names>Carlos</given-names>
</name>
</contrib>
</contrib-group>
</front-stub>
<body>
<p>Contenido en español.</p>
</body>
</sub-article>
</article>
<!-- Exemplo 7: Sub-article aninhado -->
<article article-type="research-article" xml:lang="en">
<front>
<!-- metadados -->
</front>
<body>
<!-- conteúdo -->
</body>
<sub-article article-type="translation" id="S1" xml:lang="pt">
<front-stub>
<title-group>
<article-title>Título em português</article-title>
</title-group>
<contrib-group>
<contrib contrib-type="author">
<name>
<surname>Silva</surname>
<given-names>João</given-names>
</name>
</contrib>
</contrib-group>
</front-stub>
<body>
<p>Conteúdo em português.</p>
</body>
<sub-article article-type="letter" id="L1" xml:lang="pt">
<front-stub>
<title-group>
<article-title>Carta sobre o artigo</article-title>
</title-group>
<contrib-group>
<contrib contrib-type="author">
<name>
<surname>Leitor</surname>
<given-names>Um</given-names>
</name>
</contrib>
</contrib-group>
</front-stub>
<body>
<p>Conteúdo da carta.</p>
</body>
</sub-article>
</sub-article>
</article>
XML Inválido – Caso 1: Sem @article-type (CRITICAL)
<article article-type="research-article" xml:lang="en">
<front>
<!-- metadados -->
</front>
<body>
<!-- conteúdo -->
</body>
<sub-article id="S1" xml:lang="pt">
<front-stub>
<title-group>
<article-title>Título</article-title>
</title-group>
<contrib-group>
<contrib contrib-type="author">
<name>
<surname>Silva</surname>
<given-names>João</given-names>
</name>
</contrib>
</contrib-group>
</front-stub>
<body>
<p>Conteúdo.</p>
</body>
</sub-article>
</article>
Erro esperado: Atributo @article-type é obrigatório em <sub-article>
XML Inválido – Caso 2: Sem @id (CRITICAL)
<article article-type="research-article" xml:lang="en">
<front>
<!-- metadados -->
</front>
<body>
<!-- conteúdo -->
</body>
<sub-article article-type="translation" xml:lang="pt">
<front-stub>
<title-group>
<article-title>Título</article-title>
</title-group>
<contrib-group>
<contrib contrib-type="author">
<name>
<surname>Silva</surname>
<given-names>João</given-names>
</name>
</contrib>
</contrib-group>
</front-stub>
<body>
<p>Conteúdo.</p>
</body>
</sub-article>
</article>
Erro esperado: Atributo @id é obrigatório em <sub-article>
XML Inválido – Caso 3: Sem @xml:lang (CRITICAL)
<article article-type="research-article" xml:lang="en">
<front>
<!-- metadados -->
</front>
<body>
<!-- conteúdo -->
</body>
<sub-article article-type="translation" id="S1">
<front-stub>
<title-group>
<article-title>Título</article-title>
</title-group>
<contrib-group>
<contrib contrib-type="author">
<name>
<surname>Silva</surname>
<given-names>João</given-names>
</name>
</contrib>
</contrib-group>
</front-stub>
<body>
<p>Conteúdo.</p>
</body>
</sub-article>
</article>
Erro esperado: Atributo @xml:lang é obrigatório em <sub-article>
XML Inválido – Caso 4: @article-type com valor inválido (ERROR)
<article article-type="research-article" xml:lang="en">
<front>
<!-- metadados -->
</front>
<body>
<!-- conteúdo -->
</body>
<sub-article article-type="translated" id="S1" xml:lang="pt">
<front-stub>
<title-group>
<article-title>Título</article-title>
</title-group>
<contrib-group>
<contrib contrib-type="author">
<name>
<surname>Silva</surname>
<given-names>João</given-names>
</name>
</contrib>
</contrib-group>
</front-stub>
<body>
<p>Conteúdo.</p>
</body>
</sub-article>
</article>
Erro esperado: Valor "translated" não está na lista de valores permitidos para @article-type. Use translation para traduções.
XML Inválido – Caso 5: Sem (CRITICAL)
<article article-type="research-article" xml:lang="en">
<front>
<!-- metadados -->
</front>
<body>
<!-- conteúdo -->
</body>
<sub-article article-type="translation" id="S1" xml:lang="pt">
<body>
<p>Conteúdo.</p>
</body>
</sub-article>
</article>
Erro esperado: Elemento <front-stub> é obrigatório em <sub-article>
XML Inválido – Caso 6: Sem em (CRITICAL)
<article article-type="research-article" xml:lang="en">
<front>
<!-- metadados -->
</front>
<body>
<!-- conteúdo -->
</body>
<sub-article article-type="translation" id="S1" xml:lang="pt">
<front-stub>
<title-group>
<article-title>Título</article-title>
</title-group>
</front-stub>
<body>
<p>Conteúdo.</p>
</body>
</sub-article>
</article>
Erro esperado: Elemento <contrib-group> é obrigatório em <front-stub>
XML Inválido – Caso 7: Sem em (CRITICAL)
<article article-type="research-article" xml:lang="en">
<front>
<!-- metadados -->
</front>
<body>
<!-- conteúdo -->
</body>
<sub-article article-type="translation" id="S1" xml:lang="pt">
<front-stub>
<contrib-group>
<contrib contrib-type="author">
<name>
<surname>Silva</surname>
<given-names>João</given-names>
</name>
</contrib>
</contrib-group>
</front-stub>
<body>
<p>Conteúdo.</p>
</body>
</sub-article>
</article>
Erro esperado: Elemento <article-title> é obrigatório em <front-stub>
XML Inválido – Caso 8: com (ERROR)
<article article-type="research-article" xml:lang="en">
<front>
<!-- metadados -->
</front>
<body>
<!-- conteúdo -->
</body>
<sub-article article-type="translation" id="S1" xml:lang="pt">
<front-stub>
<journal-meta>
<!-- não deve aparecer -->
</journal-meta>
<title-group>
<article-title>Título</article-title>
</title-group>
<contrib-group>
<contrib contrib-type="author">
<name>
<surname>Silva</surname>
<given-names>João</given-names>
</name>
</contrib>
</contrib-group>
</front-stub>
<body>
<p>Conteúdo.</p>
</body>
</sub-article>
</article>
Erro esperado: Elemento <journal-meta> não deve aparecer em <front-stub> (metadados são herdados do documento pai)
XML Inválido – Caso 9: com (ERROR)
<article article-type="research-article" xml:lang="en">
<front>
<!-- metadados -->
</front>
<body>
<!-- conteúdo -->
</body>
<sub-article article-type="translation" id="S1" xml:lang="pt">
<front-stub>
<article-meta>
<!-- não deve aparecer -->
</article-meta>
<title-group>
<article-title>Título</article-title>
</title-group>
<contrib-group>
<contrib contrib-type="author">
<name>
<surname>Silva</surname>
<given-names>João</given-names>
</name>
</contrib>
</contrib-group>
</front-stub>
<body>
<p>Conteúdo.</p>
</body>
</sub-article>
</article>
Erro esperado: Elemento <article-meta> não deve aparecer em <front-stub> (metadados são herdados do documento pai)
XML Inválido – Caso 10: IDs duplicados (ERROR)
<article article-type="research-article" xml:lang="en">
<front>
<!-- metadados -->
</front>
<body>
<!-- conteúdo -->
</body>
<sub-article article-type="translation" id="S1" xml:lang="pt">
<front-stub>
<title-group>
<article-title>Título em português</article-title>
</title-group>
<contrib-group>
<contrib contrib-type="author">
<name>
<surname>Silva</surname>
<given-names>João</given-names>
</name>
</contrib>
</contrib-group>
</front-stub>
<body>
<p>Conteúdo.</p>
</body>
</sub-article>
<sub-article article-type="translation" id="S1" xml:lang="es">
<front-stub>
<title-group>
<article-title>Título en español</article-title>
</title-group>
<contrib-group>
<contrib contrib-type="author">
<name>
<surname>García</surname>
<given-names>Carlos</given-names>
</name>
</contrib>
</contrib-group>
</front-stub>
<body>
<p>Contenido.</p>
</body>
</sub-article>
</article>
Erro esperado: Valor de @id duplicado em <sub-article>: "S1" (aparece 2 vezes)
XML Inválido – Caso 11: Atributos vazios (CRITICAL)
<article article-type="research-article" xml:lang="en">
<front>
<!-- metadados -->
</front>
<body>
<!-- conteúdo -->
</body>
<sub-article article-type="" id="" xml:lang="">
<front-stub>
<title-group>
<article-title>Título</article-title>
</title-group>
<contrib-group>
<contrib contrib-type="author">
<name>
<surname>Silva</surname>
<given-names>João</given-names>
</name>
</contrib>
</contrib-group>
</front-stub>
<body>
<p>Conteúdo.</p>
</body>
</sub-article>
</article>
Erro esperado: Atributos obrigatórios não podem estar vazios
XML Inválido – Caso 12: @article-type com uppercase (ERROR)
<article article-type="research-article" xml:lang="en">
<front>
<!-- metadados -->
</front>
<body>
<!-- conteúdo -->
</body>
<sub-article article-type="Translation" id="S1" xml:lang="pt">
<front-stub>
<title-group>
<article-title>Título</article-title>
</title-group>
<contrib-group>
<contrib contrib-type="author">
<name>
<surname>Silva</surname>
<given-names>João</given-names>
</name>
</contrib>
</contrib-group>
</front-stub>
<body>
<p>Conteúdo.</p>
</body>
</sub-article>
</article>
Erro esperado: Valor de @article-type deve estar em minúsculas. Use translation ao invés de Translation
XML Inválido – Caso 13: vazio (CRITICAL)
<article article-type="research-article" xml:lang="en">
<front>
<!-- metadados -->
</front>
<body>
<!-- conteúdo -->
</body>
<sub-article article-type="translation" id="S1" xml:lang="pt">
<front-stub>
</front-stub>
<body>
<p>Conteúdo.</p>
</body>
</sub-article>
</article>
Erro esperado: <front-stub> está vazio. Deve conter pelo menos <contrib-group> e <article-title>
XML Inválido – Caso 14: vazio (CRITICAL)
<article article-type="research-article" xml:lang="en">
<front>
<!-- metadados -->
</front>
<body>
<!-- conteúdo -->
</body>
<sub-article article-type="translation" id="S1" xml:lang="pt">
<front-stub>
<title-group>
<article-title></article-title>
</title-group>
<contrib-group>
<contrib contrib-type="author">
<name>
<surname>Silva</surname>
<given-names>João</given-names>
</name>
</contrib>
</contrib-group>
</front-stub>
<body>
<p>Conteúdo.</p>
</body>
</sub-article>
</article>
Erro esperado: Elemento <article-title> não pode estar vazio
XML Inválido – Caso 15: vazio (CRITICAL)
<article article-type="research-article" xml:lang="en">
<front>
<!-- metadados -->
</front>
<body>
<!-- conteúdo -->
</body>
<sub-article article-type="translation" id="S1" xml:lang="pt">
<front-stub>
<title-group>
<article-title>Título</article-title>
</title-group>
<contrib-group>
</contrib-group>
</front-stub>
<body>
<p>Conteúdo.</p>
</body>
</sub-article>
</article>
Erro esperado: Elemento <contrib-group> está vazio. Deve conter pelo menos um <contrib>
Padrão de Implementação
Diretrizes Gerais:
-
Seguir padrões existentes no repositório:
- Consultar implementações similares como
article_and_subarticles.py (validação de article)
- Usar estrutura de classes já estabelecida no packtools
- IMPORTANTE: Verificar se já existem validações parciais para
<sub-article> e integrá-las ou complementá-las
-
Internacionalização (i18n):
- OBRIGATÓRIO: Todas as mensagens devem suportar internacionalização
- Usar
advice_text e advice_params em build_response()
- Consultar conversas anteriores sobre implementação de i18n no packtools
- Referência: validações em
article_contribs.py que já implementam i18n completo
-
Validações condicionais:
- Validações que dependem de contexto devem retornar
None quando não aplicável
- Exemplo: validação de elementos em
<front-stub> só se aplica se <front-stub> existir
- Usar
filter_results() nos testes para remover None
-
Uso de build_response():
- Sempre usar
parent=self.data (dict completo, nunca string)
- Campo
response deve conter: "OK", "WARNING", "ERROR", "CRITICAL"
- Sempre fornecer
advice_text e advice_params para i18n
-
Modelo de dados:
- Criar propriedade que retorna lista de dicionários (um para cada
<sub-article>)
- Cada dict deve conter:
article_type, id, xml_lang, has_front_stub, has_contrib_group, has_article_title, has_journal_meta, has_article_meta, parent, parent_id, parent_lang
-
Lista de valores permitidos:
- Criar constante:
SUB_ARTICLE_TYPES = ["translation", "reviewer-report", "article-commentary", "letter", "reply"]
-
Validação de unicidade de IDs:
- Coletar todos os valores de
@id em <sub-article>
- Detectar duplicatas usando set ou Counter
- Reportar quais IDs estão duplicados
-
Validação de elementos em <front-stub>:
- Verificar presença de
<contrib-group> usando XPath ou .find()
- Verificar presença de
<article-title> (pode estar dentro de <title-group>)
- Verificar ausência de
<journal-meta> e <article-meta>
-
Validação de valores:
- Comparação case-sensitive: valores devem estar em minúsculas
- Trimmar espaços antes de validar
-
Suporte a aninhamento:
<sub-article> pode conter outro <sub-article>
- Validar todos os níveis de aninhamento
Testes Esperados
Casos de teste obrigatórios:
Atributos obrigatórios:
Valores de @article-type:
Presença de :
Elementos em :
Elementos proibidos em :
Unicidade de @id:
Valores de @xml:lang:
Múltiplos sub-articles:
Sub-article aninhado:
Estrutura completa:
Casos de borda:
Total esperado: ~50 testes unitários
Estrutura de testes:
- Usar
filter_results() para remover None dos resultados
- Asserções devem usar campo
response (não is_valid)
- Testes devem ser autocontidos e descritivos
- Agrupar testes por categoria (atributos, article-type, front-stub, unicidade)
Critérios de Aceite
O PR será aceito quando:
Referências
Documentação SPS:
Critérios SciELO Brasil:
Padrões JATS:
Referências internas packtools:
- Internacionalização: Consultar conversas anteriores sobre implementação de i18n
- Implementações similares:
article_and_subarticles.py (validação de article)
- Funções auxiliares:
utils.py (build_response)
Labels Sugeridas
enhancement validation SPS-1.10 scielo-brasil good-first-issue
Impacto Esperado
Antes:
- Conformidade SPS 1.10 para
<sub-article>: X% (verificar validações existentes)
- Atributos obrigatórios podem estar ausentes
- Valores incorretos de
@article-type podem passar
<front-stub> pode estar ausente ou incompleto
<journal-meta> e <article-meta> podem aparecer incorretamente
- IDs duplicados podem não ser detectados
- Elementos obrigatórios podem estar ausentes
Depois:
- Conformidade SPS 1.10 para
<sub-article>: 70% (7 de 10 regras)
- Validação CRITICAL de atributos obrigatórios
- Validação ERROR de valores permitidos de
@article-type
- Validação CRITICAL de presença de
<front-stub>
- Validação CRITICAL de elementos obrigatórios em
<front-stub>
- Validação ERROR de ausência de metadados que devem ser herdados
- Validação ERROR de unicidade de IDs
- ~50 testes unitários garantindo qualidade
- Internacionalização completa (PT/EN/ES)
Benefícios:
- Garante conformidade com Critérios SciELO Brasil (tradução obrigatória)
- Detecta ausência de atributos obrigatórios antes da publicação
- Assegura estrutura correta de
<front-stub> (sem metadados herdados)
- Previne duplicação de IDs em sub-artigos
- Melhora qualidade de documentos traduzidos
- Facilita processamento de pareceres, cartas, comentários e respostas
- Garante presença de informações essenciais (título, autores)
- Evita redundância de metadados (herança do documento pai)
- Facilita manutenção e depuração de XMLs
Observações importantes:
- Implementar internacionalização ajustando as respostas das validações ao formato da função build_response em
packtools/sps/validation/utils.py;
- Verificar e adicionar as validações no orquestrador:
packtools/sps/validation/xml_validations.py e packtools/sps/validation/xml_validator.py
- Verificar a corretude dos testes exsitentes para a validação e complementar caso necessário;
- Realizar ajustes, caso necessário, nos modelos que são utilizados pelas validações, garantindo que o ajuste não interfira em possíveis usos atuais desses modelos.
Objetivo
Implementar validações para os elementos
<sub-article>e<front-stub>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
<sub-article>e<front-stub>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
<sub-article>indica um documento aninhado dentro de outro e é obrigatório para documentos traduzidos. Sub-artigos herdam metadados do documento pai, necessitando apenas do elemento<front-stub>sem<journal-meta>e<article-meta>. Validações corretas garantem presença de atributos obrigatórios, estrutura adequada de<front-stub>, e conformidade com requisitos de tradução.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.subarticle
Regras principais conforme SPS 1.10 e Critérios SciELO Brasil:
Ocorrência:
<sub-article>pode aparecer zero ou mais vezes em<article>e<sub-article>Uso obrigatório:
Atributos obrigatórios em
<sub-article>:@article-type(obrigatório)@id(obrigatório)@xml:lang(obrigatório)Valores permitidos para
@article-type:translation- Tradução (obrigatório para documentos traduzidos)reviewer-report- Parecer (revisão por pares)article-commentary- Comentárioletter- Cartareply- RespostaElemento
<front-stub>obrigatório:<sub-article>deve conter<front-stub><journal-meta>e<article-meta>(herdam do pai)Elementos obrigatórios em
<front-stub>:<contrib-group>(obrigatório)<article-title>(obrigatório)Regra de PDF:
@article-type="translation": um PDF para cada idiomaRegras específicas para
translation:<article>, outras traduções em<sub-article><institution content-type="original"><elocation-id>, DOI,<history>: só se diferentes do originalUnicidade:
<sub-article>deve ter@idúnicoRegras a Implementar
P0 – Críticas (implementar obrigatoriamente)
@article-type@article-typeé obrigatório em<sub-article>@id@idé obrigatório em<sub-article>@xml:lang@xml:langé obrigatório em<sub-article>@article-type@article-typedeve estar na lista de valores permitidos<front-stub><front-stub>é obrigatório em<sub-article><contrib-group>em<front-stub><contrib-group>é obrigatório em<front-stub><article-title>em<front-stub><article-title>é obrigatório em<front-stub>P1 – Importantes (implementar se possível)
<journal-meta>em<front-stub><journal-meta>não deve aparecer em<front-stub>(metadados são herdados do documento pai)<article-meta>em<front-stub><article-meta>não deve aparecer em<front-stub>(metadados são herdados do documento pai)@id<sub-article>deve ter um@idúnicoP2 – Futuras (fora do escopo deste Issue)
<article>@xml:lange<article-categories><elocation-id>, DOI,<history>só aparecem se diferentes do originalArquivos a Criar/Modificar
Avaliar existentes (podem ter validações parciais):
packtools/sps/models/sub_article.pyou similar – Verificar se modelo existepacktools/sps/validation/sub_article.py– Verificar validações existentespacktools/sps/validation/rules/sub_article_rules.jsonou similar – Verificar configuraçãoCriar (se não existirem):
packtools/sps/models/sub_article.py– Modelo de extração de dadospacktools/sps/validation/sub_article.py– Validaçõespacktools/sps/validation/rules/sub_article_rules.json– Configuração de níveis de errotests/sps/validation/test_sub_article.py– Testes unitáriosReferenciar (implementações similares):
packtools/sps/validation/article_and_subarticles.py– Validação de article já existepacktools/sps/validation/utils.py– Funções auxiliares (build_response)Exemplos de XML
XML Válido (deve passar sem erros):
XML Inválido – Caso 1: Sem @article-type (CRITICAL)
Erro esperado: Atributo
@article-typeé obrigatório em<sub-article>XML Inválido – Caso 2: Sem @id (CRITICAL)
Erro esperado: Atributo
@idé obrigatório em<sub-article>XML Inválido – Caso 3: Sem @xml:lang (CRITICAL)
Erro esperado: Atributo
@xml:langé obrigatório em<sub-article>XML Inválido – Caso 4: @article-type com valor inválido (ERROR)
Erro esperado: Valor
"translated"não está na lista de valores permitidos para@article-type. Usetranslationpara traduções.XML Inválido – Caso 5: Sem (CRITICAL)
Erro esperado: Elemento
<front-stub>é obrigatório em<sub-article>XML Inválido – Caso 6: Sem em (CRITICAL)
Erro esperado: Elemento
<contrib-group>é obrigatório em<front-stub>XML Inválido – Caso 7: Sem em (CRITICAL)
Erro esperado: Elemento
<article-title>é obrigatório em<front-stub>XML Inválido – Caso 8: com (ERROR)
Erro esperado: Elemento
<journal-meta>não deve aparecer em<front-stub>(metadados são herdados do documento pai)XML Inválido – Caso 9: com (ERROR)
Erro esperado: Elemento
<article-meta>não deve aparecer em<front-stub>(metadados são herdados do documento pai)XML Inválido – Caso 10: IDs duplicados (ERROR)
Erro esperado: Valor de
@idduplicado em<sub-article>:"S1"(aparece 2 vezes)XML Inválido – Caso 11: Atributos vazios (CRITICAL)
Erro esperado: Atributos obrigatórios não podem estar vazios
XML Inválido – Caso 12: @article-type com uppercase (ERROR)
Erro esperado: Valor de
@article-typedeve estar em minúsculas. Usetranslationao invés deTranslationXML Inválido – Caso 13: vazio (CRITICAL)
Erro esperado:
<front-stub>está vazio. Deve conter pelo menos<contrib-group>e<article-title>XML Inválido – Caso 14: vazio (CRITICAL)
Erro esperado: Elemento
<article-title>não pode estar vazioXML Inválido – Caso 15: vazio (CRITICAL)
Erro esperado: Elemento
<contrib-group>está vazio. Deve conter pelo menos um<contrib>Padrão de Implementação
Diretrizes Gerais:
Seguir padrões existentes no repositório:
article_and_subarticles.py(validação de article)<sub-article>e integrá-las ou complementá-lasInternacionalização (i18n):
advice_texteadvice_paramsembuild_response()article_contribs.pyque já implementam i18n completoValidações condicionais:
Nonequando não aplicável<front-stub>só se aplica se<front-stub>existirfilter_results()nos testes para removerNoneUso de
build_response():parent=self.data(dict completo, nunca string)responsedeve conter:"OK","WARNING","ERROR","CRITICAL"advice_texteadvice_paramspara i18nModelo de dados:
<sub-article>)article_type,id,xml_lang,has_front_stub,has_contrib_group,has_article_title,has_journal_meta,has_article_meta,parent,parent_id,parent_langLista de valores permitidos:
SUB_ARTICLE_TYPES = ["translation", "reviewer-report", "article-commentary", "letter", "reply"]Validação de unicidade de IDs:
@idem<sub-article>Validação de elementos em
<front-stub>:<contrib-group>usando XPath ou.find()<article-title>(pode estar dentro de<title-group>)<journal-meta>e<article-meta>Validação de valores:
Suporte a aninhamento:
<sub-article>pode conter outro<sub-article>Testes Esperados
Casos de teste obrigatórios:
Atributos obrigatórios:
<sub-article>com todos os atributos (OK)@article-type(CRITICAL)@id(CRITICAL)@xml:lang(CRITICAL)Valores de @article-type:
translation(OK)reviewer-report(OK)article-commentary(OK)letter(OK)reply(OK)"translated"(ERROR)"review"(ERROR)"comment"(ERROR)"Translation"(ERROR)Presença de :
<sub-article>com<front-stub>(OK)<sub-article>sem<front-stub>(CRITICAL)<front-stub>vazio (CRITICAL)Elementos em :
<front-stub>com<contrib-group>(OK)<front-stub>sem<contrib-group>(CRITICAL)<contrib-group>vazio (CRITICAL)<front-stub>com<article-title>(OK)<front-stub>sem<article-title>(CRITICAL)<article-title>vazio (CRITICAL)<article-title>apenas espaços (CRITICAL)Elementos proibidos em :
<front-stub>sem<journal-meta>(OK)<front-stub>com<journal-meta>(ERROR)<front-stub>sem<article-meta>(OK)<front-stub>com<article-meta>(ERROR)Unicidade de @id:
<sub-article>com ID único (OK)<sub-article>com IDs diferentes (OK)<sub-article>com mesmo ID (ERROR)<sub-article>com IDs duplicados (ERROR)Valores de @xml:lang:
@xml:lang="pt"(OK)@xml:lang="en"(OK)@xml:lang="es"(OK)@xml:langvazio (CRITICAL)Múltiplos sub-articles:
<sub-article>(OK - zero ou mais)<sub-article>(OK)<sub-article>(OK)<sub-article>(OK)Sub-article aninhado:
<sub-article>dentro de<sub-article>(OK)Estrutura completa:
<sub-article>com<front-stub>,<body>,<back>(OK)<sub-article>sem<body>(OK - body opcional)<sub-article>sem<back>(OK - back opcional)Casos de borda:
<sub-article>completamente vazio (CRITICAL)<article-title>dentro de<title-group>(OK)<article-title>fora de<title-group>(OK - ambos aceitos)<contrib>em<contrib-group>(OK)Total esperado: ~50 testes unitários
Estrutura de testes:
filter_results()para removerNonedos resultadosresponse(nãois_valid)Critérios de Aceite
O PR será aceito quando:
<sub-article>foi analisado e integrado ou substituído adequadamentesub_article_rules.jsoncriado com todos os níveis de errobuild_response,filter_results, validações condicionais)@article-typefuncionando<front-stub>funcionando<journal-meta>e<article-meta>funcionandoReferências
Documentação SPS:
<sub-article>+<front-stub>: Sub Artigo<article>: Artigo<related-article>: Relação entre DocumentosCritérios SciELO Brasil:
Padrões JATS:
<sub-article><front-stub>Referências internas packtools:
article_and_subarticles.py(validação de article)utils.py(build_response)Labels Sugeridas
enhancementvalidationSPS-1.10scielo-brasilgood-first-issueImpacto Esperado
Antes:
<sub-article>: X% (verificar validações existentes)@article-typepodem passar<front-stub>pode estar ausente ou incompleto<journal-meta>e<article-meta>podem aparecer incorretamenteDepois:
<sub-article>: 70% (7 de 10 regras)@article-type<front-stub><front-stub>Benefícios:
<front-stub>(sem metadados herdados)Observações importantes:
packtools/sps/validation/utils.py;packtools/sps/validation/xml_validations.pyepacktools/sps/validation/xml_validator.py