Skip to content

fix: corrige extração de texto de abstract em document.py - #1034

Closed
Rossi-Luciano wants to merge 4 commits into
scieloorg:mainfrom
Rossi-Luciano:main
Closed

fix: corrige extração de texto de abstract em document.py#1034
Rossi-Luciano wants to merge 4 commits into
scieloorg:mainfrom
Rossi-Luciano:main

Conversation

@Rossi-Luciano

Copy link
Copy Markdown
Contributor

O que esse PR faz?

Corrige a extração do texto de abstract/trans-abstract em XMLArticle.get_abstracts() (publication/utils/document.py), que estava zerando o resumo de artigos publicados em duas situações independentes:

  1. Regressão no packtools: desde a versão 4.15.0 (presente também na 4.16.4 de produção), o dict retornado por Abstract.data do packtools deixou de conter a chave "text" — foi substituída, sem intenção, por graphic_href/fig_id/caption no PR scieloorg/packtools#1064. Isso afeta qualquer artigo, de qualquer coleção, processado com packtools ≥ 4.15.0 desde fev/2026.
  2. XML legado malformado: alguns artigos migrados (ex.: coleção URY) têm o texto do resumo solto, fora de <p>/<sec>, por terem sido convertidos por uma versão do scielo_migration anterior à correção feita em 2905ea5 (09/01/2026). O packtools nunca leu texto fora de <p>/<sec> — nem antes nem depois da regressão do item 1 — então esse caso persiste independentemente do fix no packtools.

get_abstracts() agora tenta, em cascata: (a) a chave text nativa do packtools, (b) recomposição a partir de p/sections (mesma lógica que a property text do packtools já fazia antes da regressão — cobre o item 1 caso o packtools ainda não tenha sido corrigido), (c) extração bruta do XML ignorando o <title> (cobre o item 2). Também isola exceções por nó, para que um abstract/trans-abstract malformado não descarte os resumos dos demais nós do mesmo artigo.

Onde a revisão poderia começar?

publication/utils/document.py, classe XMLArticle, método get_abstracts() (e os dois métodos auxiliares logo abaixo, _compose_abstract_text_from_item e _extract_raw_abstract_text).

Como este poderia ser testado manualmente?

  1. Publicar um artigo com resumo estruturado normal (<p> ou <sec><p>) e verificar que o abstract/abstracts do payload de publicação continua preenchido.
  2. Usar o XML anexado à issue [Migração de Artigos XMLs] Casos onde o texto do resumo não aparecem #1031 (resumo da URY, sem <p>) e verificar que o resumo passa a ser extraído.
  3. Rodar python -m unittest publication.utils.test_document — os 4 novos testes de regressão cobrem: resumo simples com <p>, resumo estruturado com <sec>, resumo sem <p> (estrutura real da issue), e isolamento de falha (um nó malformado não zera os demais).

Validei manualmente os três cenários acima contra as duas versões de packtools relevantes — a pinada em requirements/base.txt (4.16.8) e a de produção (4.16.4, instalada a partir do tag correspondente) — e contra o XML real anexado à issue: os 9 testes do módulo passam nas duas versões, e a extração funciona ponta a ponta nos dois idiomas do artigo de exemplo.

Algum cenário de contexto que queira dar?

Este fix não depende de nenhuma das duas correções de raiz relacionadas, e continua funcionando corretamente mesmo depois delas serem feitas:

  • Quando o PR de correção do packtools (restaurando a chave text) for aberto e for para produção, o item (a) da cascata passa a funcionar de novo e os itens (b)/(c) seguem como fallback, sem conflito.
  • A correção no scielo_migration (commit 2905ea5, já em produção da ferramenta desde jan/2026) evita que novas conversões produzam o padrão malformado do item 2, mas não corrige retroativamente os XMLs já convertidos/migrados antes dessa data — por isso o item (c) da cascata continua necessário para tolerar esse legado na publicação, independentemente de uma eventual remigração desses artigos específicos.

Também identifiquei, mas não mexi neste PR: existe um parâmetro abstract em ArticlePayload.add_main_metadata() (publication/api/document.py) que nunca é atribuído a self.data["abstract"] — código morto/vestigial, coerente com XMLArticle.get_main_metadata() sempre retornar abstract=None. Não afeta este bug, mas é um ponto de limpeza para um PR separado.

Screenshots

Não aplicável (correção de lógica de processamento, sem interface).

Quais são os tickets relevantes?

Referências


Segurança da informação (NSI.04)

Este PR manipula dados sensíveis ou pessoais (LGPD)?

  • Não

Este PR altera autenticação, autorização, controle de acesso ou gerenciamento de sessão?

  • Não

Este PR introduz, atualiza ou remove dependências de terceiros?

  • Não (troca apenas o caminho de import de uma classe já existente dentro do packtools já pinado — packtools.sps.models.v2.abstract.XMLAbstractspacktools.sps.validation.models.abstract.Abstract, mesma dependência, sem alteração de versão)

Este PR foi validado pelo pipeline de segurança (SonarQube / Trivy)?

  • Não aplicável a este PR — sem novas dependências nem superfície de ataque nova

Este PR concatena, monta ou executa comandos SQL, HTML ou JavaScript a partir de entrada externa?

  • Não

Este PR expõe novos endpoints, telas ou serviços?

  • Não

Algum segredo, senha, chave ou token está sendo adicionado ao código-fonte?

  • Não, nenhum segredo foi commitado

Rossi-Luciano and others added 2 commits July 29, 2026 18:17
O texto de abstract/trans-abstract parava de ser extraído em
XMLArticle.get_abstracts() porque o dict retornado por
XMLAbstracts.get_abstracts() do packtools (>=4.15.0) deixou de conter
a chave "text" (regressão introduzida em scieloorg/packtools#1064, que
substituiu essa linha por graphic_href/fig_id/caption sem intenção).
Isso zerava o abstract de qualquer artigo processado desde então, em
qualquer coleção.

Alguns XMLs migrados legados (ex.: coleção URY) também têm o texto do
resumo solto, fora de <p>/<sec>, fora do padrão SPS - o que faz o
texto ficar vazio mesmo com a chave "text" presente.

get_abstracts() agora tenta, em ordem, a chave "text" do packtools, a
recomposição a partir de p/sections e a extração bruta do XML
ignorando o <title>, para cobrir os dois casos. Também isola exceções
por nó, para que um abstract malformado não descarte os demais do
mesmo artigo.

Refs: scieloorg#1031, scieloorg/packtools#1064

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Cobre XMLArticle.get_abstracts(): resumo simples com <p>, resumo
estruturado com <sec>, resumo sem <p> (estrutura do XML real da
issue), artigo sem abstract, e isolamento de falha - um
abstract/trans-abstract malformado não pode descartar os resumos dos
demais nós do mesmo artigo.

Refs: scieloorg#1031

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Comment thread publication/utils/document.py Outdated
import logging

from packtools.sps.models.v2.abstract import XMLAbstracts
from packtools.sps.validation.models.abstract import Abstract

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Rossi-Luciano não misturar modelo para obter os dados com os modelos de validação. Eles tem funções diferentes. No modelo de validação teria que evidenciar, por exemplo, ausência de resumo se tivesse que existir resumo. No caso de modelo para obter os dados, mesmo que um resumo não existisse não precisaria retornar o abstract de um determinado idioma com None, por exemplo.

Comment thread publication/utils/document.py Outdated
Comment on lines +165 to +167
_STANDARD_ABSTRACTS_XPATH = (
".//abstract[not(@abstract-type)] | .//trans-abstract[not(@abstract-type)]"
)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Rossi-Luciano isso deveria estar no packtools e ficar transparente no upload ao usar um modelo do packtools

Comment thread publication/utils/document.py Outdated
yield {"language": lang, "text": text}
except Exception as e:
return []
nodes = self.xmltree.xpath(self._STANDARD_ABSTRACTS_XPATH)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Rossi-Luciano este código todo deveria ser no packtools. O modelo para obter os dados deve considerar que o xml não está perfeito. Mas cuidado para que os xmls que estiverem de acordo com o esperado retornem os dados corretamente. Corrija o modelo from packtools.sps.models.v2.abstract import XMLAbstracts acrescentando o caso indicado no issue e cuidando para que os demais casos sigam funcionando

robertatakenaka pushed a commit to scieloorg/packtools that referenced this pull request Aug 3, 2026
Abstract.text (e, por consequência, Abstract.data["text"]) só lia
title/p de <sec> ou <p> soltos, e retornava vazio quando o resumo
legado tinha texto solto diretamente sob <abstract>/<trans-abstract>,
fora de <p>/<sec>. Isso ocorre em alguns XMLs migrados (ex.: coleção
URY) convertidos por versões do scielo_migration anteriores à correção
em scieloorg/scielo_migration@2905ea5.

Adiciona fallback: quando não há <sec> nem <p> com conteúdo, extrai o
texto bruto do nó via itertext(), removendo o texto do <title> quando
presente. Comportamento existente é preservado (title sozinho, sem
texto solto, continua retornando "").

Refs: scieloorg/scms-upload#1031, scieloorg/scms-upload#1034
document.py voltava a extrair texto de abstract manualmente
(packtools.sps.validation.models.abstract.Abstract + XPath e fallback
próprios) porque o packtools 4.16.8 não expunha a chave "text" e nunca
lia resumos sem wrapper <p>/<sec> (caso legado da coleção URY).

Os dois problemas foram corrigidos no packtools:
- chave "text" restaurada em scieloorg/packtools#1261 (4.16.9)
- texto sem <p>/<sec> extraído em scieloorg/packtools#1272 (4.16.11)

Com o pin subindo para 4.16.11, get_abstracts() volta a usar
XMLAbstracts(self.xmltree).get_abstracts() diretamente, transparente,
como antes deste bug — sem duplicar lógica de extração que pertence ao
packtools, conforme apontado no review de scieloorg#1034.

Refs: scieloorg#1031, scieloorg/packtools#1261, scieloorg/packtools#1272
@robertatakenaka

Copy link
Copy Markdown
Member

PR não resolve, mas ao usar o packtools 4.16.11, problema é resolvido

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Migração de Artigos XMLs] Casos onde o texto do resumo não aparecem

2 participants