Skip to content

Criar validações para o elemento <response> #1108

@Rossi-Luciano

Description

@Rossi-Luciano

Objetivo

Implementar validações para o elemento <response> conforme a especificação SPS 1.10, aumentando a conformidade de X% para 70% (7 de 10 regras).

Nota: Algumas validações para <response> podem já estar parcialmente implementadas no repositório. Este Issue visa reavaliar, complementar e garantir cobertura completa das regras SPS 1.10.


Contexto

O elemento <response> identifica um conjunto de respostas referente a uma carta ou comentário, obrigatoriamente publicadas juntamente com a carta/comentário. É usado quando há múltiplas respostas no mesmo documento. Validações corretas garantem presença de atributos obrigatórios, unicidade de IDs, e estrutura mínima necessária.

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.response

Regras principais conforme SPS 1.10:

  1. Ocorrência:

    • <response> pode aparecer zero ou mais vezes em <article> e <sub-article>
  2. Contexto de uso:

    • Tag para identificar conjunto de respostas referente a carta ou comentário
    • Obrigatoriamente publicadas juntamente com carta ou comentário
    • Se apenas uma resposta: usar <sub-article article-type="reply">
    • Se publicado com DOI separadamente: usar <article article-type="reply">
  3. Atributos obrigatórios:

    • @response-type="reply" (obrigatório)
    • @xml:lang (obrigatório)
    • @id (obrigatório)
  4. Unicidade de IDs:

    • Deve-se usar um @id diferente para cada <response>
  5. Estrutura esperada:

    • <front-stub> - Metadados da resposta
    • <body> - Conteúdo da resposta
    • <back> - Seção final (opcional, pode conter <ref-list>)

Regras a Implementar

P0 – Críticas (implementar obrigatoriamente)

# Regra Nível Descrição
1 Validar presença de @response-type CRITICAL O atributo @response-type é obrigatório em <response>
2 Validar valor de @response-type ERROR O valor de @response-type deve ser "reply"
3 Validar presença de @xml:lang CRITICAL O atributo @xml:lang é obrigatório em <response>
4 Validar presença de @id CRITICAL O atributo @id é obrigatório em <response>
5 Validar unicidade de @id ERROR Cada <response> deve ter um @id único (não pode repetir valores)

P1 – Importantes (implementar se possível)

# Regra Nível Descrição
6 Validar presença de <front-stub> WARNING Recomenda-se que <response> contenha <front-stub> com metadados da resposta
7 Validar presença de <body> WARNING Recomenda-se que <response> contenha <body> com o conteúdo da resposta

P2 – Futuras (fora do escopo deste Issue)

# Regra Motivo de exclusão
8 Validar contexto de uso (carta/comentário) Média complexidade - requer validação do article-type do documento pai
9 Validar uso de sub-article para resposta única Alta complexidade - requer análise de quantidade e contexto
10 Validar formato de @id conforme sugestões SPS Baixa prioridade - formato livre permitido

Arquivos a Criar/Modificar

Avaliar existentes (podem ter validações parciais):

  • packtools/sps/models/response.py ou similar – Verificar se modelo existe
  • packtools/sps/validation/response.py – Verificar validações existentes
  • packtools/sps/validation/rules/response_rules.json ou similar – Verificar configuração

Criar (se não existirem):

  • packtools/sps/models/response.py – Modelo de extração de dados
  • packtools/sps/validation/response.py – Validações
  • packtools/sps/validation/rules/response_rules.json – Configuração de níveis de erro
  • tests/sps/validation/test_response.py – Testes unitários

Referenciar (implementações similares):

  • packtools/sps/validation/sub_article.py – Validação de estrutura similar
  • packtools/sps/validation/utils.py – Funções auxiliares (build_response)

Exemplos de XML

XML Válido (deve passar sem erros):

<!-- Exemplo 1: Duas respostas em um documento -->
<article article-type="letter">
    <front>
        <!-- metadados da carta -->
    </front>
    <body>
        <!-- conteúdo da carta -->
    </body>
    <response response-type="reply" xml:lang="en" id="S1">
        <front-stub>
            <contrib-group>
                <contrib contrib-type="author">
                    <name>
                        <surname>Smith</surname>
                        <given-names>John</given-names>
                    </name>
                </contrib>
            </contrib-group>
        </front-stub>
        <body>
            <p>First response content.</p>
        </body>
        <back>
            <ref-list>
                <!-- referências -->
            </ref-list>
        </back>
    </response>
    <response response-type="reply" xml:lang="en" id="S2">
        <front-stub>
            <contrib-group>
                <contrib contrib-type="author">
                    <name>
                        <surname>Jones</surname>
                        <given-names>Mary</given-names>
                    </name>
                </contrib>
            </contrib-group>
        </front-stub>
        <body>
            <p>Second response content.</p>
        </body>
    </response>
</article>

<!-- Exemplo 2: Resposta em português -->
<article article-type="letter">
    <front>
        <!-- metadados -->
    </front>
    <body>
        <!-- conteúdo -->
    </body>
    <response response-type="reply" xml:lang="pt" id="R01">
        <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 da resposta.</p>
        </body>
    </response>
</article>

<!-- Exemplo 3: Múltiplas respostas com IDs diferentes -->
<article article-type="commentary">
    <front>
        <!-- metadados -->
    </front>
    <body>
        <!-- conteúdo -->
    </body>
    <response response-type="reply" xml:lang="en" id="resp1">
        <front-stub>
            <!-- metadados da resposta 1 -->
        </front-stub>
        <body>
            <p>Response 1.</p>
        </body>
    </response>
    <response response-type="reply" xml:lang="en" id="resp2">
        <front-stub>
            <!-- metadados da resposta 2 -->
        </front-stub>
        <body>
            <p>Response 2.</p>
        </body>
    </response>
    <response response-type="reply" xml:lang="en" id="resp3">
        <front-stub>
            <!-- metadados da resposta 3 -->
        </front-stub>
        <body>
            <p>Response 3.</p>
        </body>
    </response>
</article>

<!-- Exemplo 4: Resposta mínima (sem back) -->
<article article-type="letter">
    <front>
        <!-- metadados -->
    </front>
    <body>
        <!-- conteúdo -->
    </body>
    <response response-type="reply" xml:lang="es" id="S1">
        <front-stub>
            <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 de la respuesta.</p>
        </body>
    </response>
</article>

<!-- Exemplo 5: Resposta em sub-article -->
<article article-type="letter">
    <front>
        <!-- metadados -->
    </front>
    <body>
        <!-- conteúdo -->
    </body>
    <sub-article article-type="translation" xml:lang="pt">
        <front-stub>
            <!-- tradução -->
        </front-stub>
        <body>
            <!-- conteúdo traduzido -->
        </body>
        <response response-type="reply" xml:lang="pt" id="S1-pt">
            <front-stub>
                <!-- metadados da resposta traduzida -->
            </front-stub>
            <body>
                <p>Resposta em português.</p>
            </body>
        </response>
    </sub-article>
</article>

XML Inválido – Caso 1: Sem @response-type (CRITICAL)

<article article-type="letter">
    <front>
        <!-- metadados -->
    </front>
    <body>
        <!-- conteúdo -->
    </body>
    <response xml:lang="en" id="S1">
        <front-stub>
            <!-- metadados -->
        </front-stub>
        <body>
            <p>Response content.</p>
        </body>
    </response>
</article>

Erro esperado: Atributo @response-type é obrigatório em <response>

XML Inválido – Caso 2: @response-type com valor incorreto (ERROR)

<article article-type="letter">
    <front>
        <!-- metadados -->
    </front>
    <body>
        <!-- conteúdo -->
    </body>
    <response response-type="answer" xml:lang="en" id="S1">
        <front-stub>
            <!-- metadados -->
        </front-stub>
        <body>
            <p>Response content.</p>
        </body>
    </response>
</article>

Erro esperado: Valor de @response-type deve ser "reply". Valor encontrado: "answer"

XML Inválido – Caso 3: Sem @xml:lang (CRITICAL)

<article article-type="letter">
    <front>
        <!-- metadados -->
    </front>
    <body>
        <!-- conteúdo -->
    </body>
    <response response-type="reply" id="S1">
        <front-stub>
            <!-- metadados -->
        </front-stub>
        <body>
            <p>Response content.</p>
        </body>
    </response>
</article>

Erro esperado: Atributo @xml:lang é obrigatório em <response>

XML Inválido – Caso 4: Sem @id (CRITICAL)

<article article-type="letter">
    <front>
        <!-- metadados -->
    </front>
    <body>
        <!-- conteúdo -->
    </body>
    <response response-type="reply" xml:lang="en">
        <front-stub>
            <!-- metadados -->
        </front-stub>
        <body>
            <p>Response content.</p>
        </body>
    </response>
</article>

Erro esperado: Atributo @id é obrigatório em <response>

XML Inválido – Caso 5: IDs duplicados (ERROR)

<article article-type="letter">
    <front>
        <!-- metadados -->
    </front>
    <body>
        <!-- conteúdo -->
    </body>
    <response response-type="reply" xml:lang="en" id="S1">
        <front-stub>
            <!-- metadados -->
        </front-stub>
        <body>
            <p>First response.</p>
        </body>
    </response>
    <response response-type="reply" xml:lang="en" id="S1">
        <front-stub>
            <!-- metadados -->
        </front-stub>
        <body>
            <p>Second response.</p>
        </body>
    </response>
</article>

Erro esperado: Valor de @id duplicado em <response>. Cada <response> deve ter um @id único. ID duplicado: "S1"

XML Inválido – Caso 6: Atributos vazios (CRITICAL)

<article article-type="letter">
    <front>
        <!-- metadados -->
    </front>
    <body>
        <!-- conteúdo -->
    </body>
    <response response-type="" xml:lang="" id="">
        <front-stub>
            <!-- metadados -->
        </front-stub>
        <body>
            <p>Response content.</p>
        </body>
    </response>
</article>

Erro esperado: Atributos obrigatórios não podem estar vazios

XML Inválido – Caso 7: @response-type apenas espaços (CRITICAL)

<article article-type="letter">
    <front>
        <!-- metadados -->
    </front>
    <body>
        <!-- conteúdo -->
    </body>
    <response response-type="   " xml:lang="en" id="S1">
        <front-stub>
            <!-- metadados -->
        </front-stub>
        <body>
            <p>Response content.</p>
        </body>
    </response>
</article>

Erro esperado: Atributo @response-type não pode conter apenas espaços

XML Inválido – Caso 8: @response-type com uppercase (ERROR)

<article article-type="letter">
    <front>
        <!-- metadados -->
    </front>
    <body>
        <!-- conteúdo -->
    </body>
    <response response-type="Reply" xml:lang="en" id="S1">
        <front-stub>
            <!-- metadados -->
        </front-stub>
        <body>
            <p>Response content.</p>
        </body>
    </response>
</article>

Erro esperado: Valor de @response-type deve estar em minúsculas. Use reply ao invés de Reply

XML Inválido – Caso 9: Sem (WARNING)

<article article-type="letter">
    <front>
        <!-- metadados -->
    </front>
    <body>
        <!-- conteúdo -->
    </body>
    <response response-type="reply" xml:lang="en" id="S1">
        <body>
            <p>Response content.</p>
        </body>
    </response>
</article>

Erro esperado: (WARNING) Recomenda-se que <response> contenha <front-stub> com metadados da resposta

XML Inválido – Caso 10: Sem (WARNING)

<article article-type="letter">
    <front>
        <!-- metadados -->
    </front>
    <body>
        <!-- conteúdo -->
    </body>
    <response response-type="reply" xml:lang="en" id="S1">
        <front-stub>
            <contrib-group>
                <contrib contrib-type="author">
                    <name>
                        <surname>Smith</surname>
                        <given-names>John</given-names>
                    </name>
                </contrib>
            </contrib-group>
        </front-stub>
    </response>
</article>

Erro esperado: (WARNING) Recomenda-se que <response> contenha <body> com o conteúdo da resposta

XML Inválido – Caso 11: vazio (CRITICAL + WARNING)

<article article-type="letter">
    <front>
        <!-- metadados -->
    </front>
    <body>
        <!-- conteúdo -->
    </body>
    <response response-type="reply" xml:lang="en" id="S1">
    </response>
</article>

Erro esperado: (WARNING) <response> está vazio. Adicione <front-stub> e <body>

XML Inválido – Caso 12: Três IDs duplicados (ERROR)

<article article-type="letter">
    <front>
        <!-- metadados -->
    </front>
    <body>
        <!-- conteúdo -->
    </body>
    <response response-type="reply" xml:lang="en" id="R1">
        <front-stub>
            <!-- metadados -->
        </front-stub>
        <body>
            <p>Response 1.</p>
        </body>
    </response>
    <response response-type="reply" xml:lang="en" id="R1">
        <front-stub>
            <!-- metadados -->
        </front-stub>
        <body>
            <p>Response 2.</p>
        </body>
    </response>
    <response response-type="reply" xml:lang="en" id="R2">
        <front-stub>
            <!-- metadados -->
        </front-stub>
        <body>
            <p>Response 3.</p>
        </body>
    </response>
</article>

Erro esperado: Valor de @id duplicado em <response>: "R1" (aparece 2 vezes)


Padrão de Implementação

Diretrizes Gerais:

  1. Seguir padrões existentes no repositório:

    • Consultar implementações similares como sub_article.py (estrutura similar)
    • Usar estrutura de classes já estabelecida no packtools
    • IMPORTANTE: Verificar se já existem validações parciais para <response> e integrá-las ou complementá-las
  2. 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
  3. Validações condicionais:

    • Validações que dependem de contexto devem retornar None quando não aplicável
    • Exemplo: validação de <front-stub> e <body> são WARNING, não CRITICAL
    • Usar filter_results() nos testes para remover None
  4. 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
  5. Modelo de dados:

    • Criar propriedade que retorna lista de dicionários (um para cada <response>)
    • Cada dict deve conter: response_type, xml_lang, id, has_front_stub, has_body, has_back, parent, parent_id, parent_lang
  6. Validação de unicidade de IDs:

    • Coletar todos os valores de @id em <response>
    • Detectar duplicatas usando set ou Counter
    • Reportar quais IDs estão duplicados
  7. Validação de valor:

    • Comparação case-sensitive: @response-type deve ser exatamente "reply" (minúsculas)
    • Trimmar espaços antes de validar
  8. Validação de elementos filhos:

    • Verificar presença de <front-stub> usando XPath ou .find()
    • Verificar presença de <body> usando XPath ou .find()
    • Nível WARNING (recomendado, não obrigatório)

Testes Esperados

Casos de teste obrigatórios:

Atributos obrigatórios:

  • <response> com todos os atributos obrigatórios (OK)
  • Sem @response-type (CRITICAL)
  • Sem @xml:lang (CRITICAL)
  • Sem @id (CRITICAL)
  • Atributos vazios (CRITICAL)
  • Atributos apenas com espaços (CRITICAL)

Valor de @response-type:

  • @response-type="reply" (OK)
  • @response-type="answer" (ERROR)
  • @response-type="response" (ERROR)
  • @response-type="Reply" (ERROR - uppercase)
  • @response-type="REPLY" (ERROR - uppercase)

Valores de @xml:lang:

  • @xml:lang="en" (OK)
  • @xml:lang="pt" (OK)
  • @xml:lang="es" (OK)
  • @xml:lang vazio (CRITICAL)

Unicidade de @id:

  • Um <response> com ID único (OK)
  • Dois <response> com IDs diferentes (OK)
  • Três <response> com IDs diferentes (OK)
  • Dois <response> com mesmo ID (ERROR)
  • Três <response> com dois IDs iguais (ERROR)
  • Múltiplos <response> todos com mesmo ID (ERROR)

Presença de elementos filhos:

  • <response> com <front-stub> (OK)
  • <response> sem <front-stub> (WARNING)
  • <response> com <body> (OK)
  • <response> sem <body> (WARNING)
  • <response> com <front-stub> e <body> (OK)
  • <response> sem <front-stub> nem <body> (WARNING)
  • <response> com <back> (OK - opcional)
  • <response> sem <back> (OK - opcional)

Múltiplos responses:

  • Artigo sem <response> (OK - zero ou mais vezes)
  • Artigo com um <response> (OK)
  • Artigo com dois <response> (OK)
  • Artigo com três ou mais <response> (OK)

Contextos:

  • <response> em <article> (OK)
  • <response> em <sub-article> (OK)

Casos de borda:

  • <response> vazio (WARNING - falta estrutura)
  • ID com caracteres especiais (OK)
  • ID numérico (OK)
  • ID alfanumérico (OK)
  • @xml:lang com código de 2 letras (OK)
  • @xml:lang com código de 5 letras (OK - ex: pt-BR)

Total esperado: ~40 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, valores, unicidade, elementos)

Critérios de Aceite

O PR será aceito quando:

  • Verificação de validações existentes: Código existente para <response> foi analisado e integrado ou substituído adequadamente
  • Todas as regras P0 implementadas (5 validações CRITICAL/ERROR)
  • Todas as regras P1 implementadas (2 validações WARNING)
  • Testes unitários passando com cobertura mínima de ~40 casos
  • Nenhum teste existente quebrado
  • Arquivo response_rules.json criado com todos os níveis de erro
  • Internacionalização completa em todas as mensagens (i18n obrigatório)
  • Código seguindo padrões do packtools (build_response, filter_results, validações condicionais)
  • Modelo de dados criado com extração adequada de todos os atributos
  • Validação de unicidade de IDs funcionando (detecta duplicatas)
  • Validação de valor case-sensitive (reply minúsculo)
  • Validação de elementos filhos (front-stub, body) funcionando
  • Suporte para múltiplos <response> (zero ou mais vezes)
  • Documentação inline clara (docstrings)

Referências

Documentação SPS:

Padrões JATS:

Referências internas packtools:

  • Internacionalização: Consultar conversas anteriores sobre implementação de i18n
  • Implementações similares: sub_article.py (estrutura similar)
  • Funções auxiliares: utils.py (build_response)

Labels Sugeridas

enhancement validation SPS-1.10 good-first-issue


Impacto Esperado

Antes:

  • Conformidade SPS 1.10 para <response>: X% (verificar validações existentes)
  • Atributos obrigatórios podem estar ausentes
  • Valores incorretos de @response-type podem passar
  • IDs duplicados podem não ser detectados
  • Estrutura mínima não verificada

Depois:

  • Conformidade SPS 1.10 para <response>: 70% (7 de 10 regras)
  • Validação CRITICAL de atributos obrigatórios
  • Validação ERROR de valor correto (reply)
  • Validação ERROR de unicidade de IDs
  • Validação WARNING de elementos recomendados (front-stub, body)
  • ~40 testes unitários garantindo qualidade
  • Internacionalização completa (PT/EN/ES)

Benefícios:

  • Melhora a qualidade dos XMLs SciELO
  • Garante estrutura adequada para múltiplas respostas
  • Detecta IDs duplicados antes da publicação
  • Assegura presença de atributos obrigatórios
  • Promove estrutura mínima recomendada (front-stub + body)
  • Facilita processamento de respostas a cartas/comentários
  • Melhora organização de debates científicos
  • Garante conformidade com padrões SPS
  • Facilita manutenção e depuração de XMLs

Metadata

Metadata

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions