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

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.

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.

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