Adiciona related_item para os relacionamentos hasReview, isCommentOn, isReplyTo, isReviewOf, hasPreprint, etc - #330
Conversation
Mapeia tipos SPS e article_type para relationship-type válidos em relations.xsd e inclui testes de validação XSD 4.4.0. Co-authored-by: Cursor <cursoragent@cursor.com>
Usa PropertyMock para compatibilidade com a property related_documents do xylose. Co-authored-by: Cursor <cursoragent@cursor.com>
Usa related_article_type do SciELO/JATS, desambigua commentary/letter pelo document_type do artigo corrente e ignora tipos sem equivalente no relations.xsd. Co-authored-by: Cursor <cursoragent@cursor.com>
|
@samuelveigarangel justificar o motivo de |
| RELATION_TYPES = { | ||
| 'commentary-article': ('inter_work_relation', 'isCommentOn'), | ||
| 'reply': ('inter_work_relation', 'isReplyTo'), | ||
| 'reviewed-article': ('inter_work_relation', 'isReviewOf'), | ||
| 'reviewer-report': ('inter_work_relation', 'hasReview'), | ||
| 'preprint': ('intra_work_relation', 'hasPreprint'), | ||
| 'article-commentary': ('inter_work_relation', 'isCommentOn'), | ||
| 'letter': ('inter_work_relation', 'isReplyTo'), | ||
| 'book-review': ('inter_work_relation', 'isReviewOf'), | ||
| 'editorial': ('inter_work_relation', 'isCommentOn'), | ||
| } |
| related_articles = getattr(raw, 'related_documents', None) | ||
| if callable(related_articles): | ||
| related_articles = related_articles() |
There was a problem hiding this comment.
try:
related_articles = raw.related_documents()
except (AttributeError, TypeError):
....| program_node = self._get_or_create_program(journal_article_node) | ||
|
|
||
| for related_article in related_articles: | ||
| document_type = related_article.get('document_type') |
There was a problem hiding this comment.
@samuelveigarangel no xylose vc não usou o mesmo nome do SPS que é related_article_type ... ou este document_type é o article-type de article?
| description_node = ET.Element('description') | ||
| description_node.text = raw.original_title() | ||
| related_item_node.append(description_node) | ||
| current_document_type = getattr(raw, 'document_type', None) |
There was a problem hiding this comment.
@samuelveigarangel é realemente necessário usar isso no lugar de raw.document_type?
There was a problem hiding this comment.
Só pra evitar atributteError mas acredito que sempre vai existir document_type
pitangainnovare
left a comment
There was a problem hiding this comment.
Encontrei um caso real que não está coberto pelos testes atuais. Faltou validar o outro lado da relação: os pareceres de revisão .a e .b, que devem apontar para o artigo avaliado por meio de isReviewOf.
Os registros usados na validação foram:
- Parecer
.a:S2237-96222025000100800 - Parecer
.b:S2237-96222025000100801
É possível reproduzir o problema com:
curl -fsS \
"https://articlemeta.scielo.org/api/v1/article/?collection=scl&code=S2237-96222025000100800" \
-o /tmp/article-a.json
curl -fsS \
"https://articlemeta.scielo.org/api/v1/article/?collection=scl&code=S2237-96222025000100801" \
-o /tmp/article-b.json
python - <<'PY'
import json
from pathlib import Path
from articlemeta.export import Export
for suffix in ("a", "b"):
with open(f"/tmp/article-{suffix}.json", encoding="utf-8") as source:
article = json.load(source)
Path(f"crossref-{suffix}.xml").write_bytes(
Export(article).pipeline_crossref()
)
PYOs XML são gerados com sucesso, mas ambos ficam com o programa de relações vazio:
<program xmlns="http://www.crossref.org/relations.xsd"/>A causa é uma diferença entre o valor presente nos dados reais e o valor esperado pelo mapeamento do PR.
O ArticleMeta fornece a relação no campo legado v241:
"v241": [
{
"i": "10.1590/S2237-96222024v33e20240180.en",
"t": "peer-reviewed-material",
"_": "",
"n": "doi"
}
]O xylose não cria, traduz ou normaliza o valor "peer-reviewed-material". A propriedade related_documents apenas repassa os subcampos de v241:
@property
def related_documents(self):
if "v241" in self.data["article"]:
related_documents = []
for related_document in self.data["article"].get("v241"):
item = {}
if "i" in related_document:
item["id"] = related_document["i"]
if "t" in related_document:
item["related_article_type"] = related_document["t"]
if "n" in related_document:
item["ext_link_type"] = related_document["n"]
related_documents.append(item)
if len(related_documents) > 0:
return related_documentsPortanto, a linha:
item["related_article_type"] = related_document["t"]repassa diretamente o valor de v241.t, resultando em:
{
"id": "10.1590/S2237-96222024v33e20240180.en",
"related_article_type": "peer-reviewed-material",
"ext_link_type": "doi",
}Isso também pode ser confirmado diretamente:
python - <<'PY'
import json
from xylose.scielodocument import Article
with open("/tmp/article-a.json", encoding="utf-8") as source:
article = Article(json.load(source))
print(article.related_documents)
PYPor outro lado, o mapeamento implementado no exportador reconhece somente:
"reviewed-article": ("inter_work_relation", "isReviewOf")Como "peer-reviewed-material" não existe nesse mapeamento, _resolve_relation() retorna None. A relação é silenciosamente descartada e o elemento <program> permanece vazio.
Os testes atuais utilizam "reviewed-article" na estrutura simulada de related_documents. Por isso, passam sem cobrir o valor efetivamente recebido do ArticleMeta e repassado sem transformação pelo xylose.
Pelo que entendi, precisamos contemplar o valor encontrado nos dados reais:
"peer-reviewed-material": ("inter_work_relation", "isReviewOf")Também é necessário adicionar pelo menos um teste com a estrutura real de related_documents, incluindo related_article_type="peer-reviewed-material".
O resultado esperado para cada parecer é uma relação deste formato:
<program xmlns="http://www.crossref.org/relations.xsd">
<related_item>
<inter_work_relation
relationship-type="isReviewOf"
identifier-type="doi">DOI_DO_ARTIGO_AVALIADO</inter_work_relation>
</related_item>
</program>|
Muito bom @pitangainnovare . No documento do sps não está previsto esse valor para related-article |
Corrige hasTranslation/isTranslationOf no artigo original e nas traduções, expande o mapeamento de related-article-type e emite rel:program apenas para tipos mapeados. Co-authored-by: Cursor <cursoragent@cursor.com>
|
@samuelveigarangel, seguem três pontos sobre as novas alterações:
|
|
@rafaelpezzuto Para |
…vazio. Adiciona cobertura para peer-reviewed-material/reviewer-report e reply como documento principal, criando <program> só quando há related_item. Co-authored-by: Cursor <cursoragent@cursor.com>
O que esse PR faz?
Expande o
XMLProgramRelatedItemPipepara exportar documentos relacionados no depósito Crossref, consumindo a propertyrelated_documentsdo xylose (campo legadov241).As principais mudanças são:
article_typepararelationship-typeválidos emrelations.xsd(hasReview,isCommentOn,isReplyTo,isReviewOf,hasPreprint, etc.).<program>,<related_item>,<description>e relaçõesinter_work/intra_work.isTranslationOf/hasTranslation).Tipos editoriais sem correspondência em
relations.xsd(ex.:corrected-article,retracted-article) são ignorados.Onde a revisão poderia começar?
Comece por
articlemeta/export_crossref.py, na classeXMLProgramRelatedItemPipe— especialmenteRELATION_TYPES,_transform_related_articlese os helpers_create_program,_get_or_create_programe_create_related_item.Em seguida, veja os testes em
tests/test_export_crossref.py:test_related_articles_validating_against_schematest_related_item_for_supported_related_articlestest_related_item_for_article_type_mappingsComo este poderia ser testado manualmente?
related_documents(dependência do PR Add related_documents property and tests to Article xylose#207).v241, por exemplo:curl -s "https://articlemeta.scielo.org/api/v1/article/?collection=scl&code=S2237-96222025000100200" -o /tmp/article.json<program xmlns="http://www.crossref.org/relations.xsd">com<inter_work_relation relationship-type="hasReview">para pareceres (reviewer-report).Algum cenário de contexto que queira dar?
Este PR depende da property
related_documentsno xylose, que abstrai o campov241e retorna dicionários comidentifier,document_type,identifier_typeelabel.A distinção entre
inter_work_relationeintra_work_relationsegue orelations.xsd: relações entre obras distintas (comentários, pareceres, resenhas) usaminter_work; variantes da mesma obra (traduções, preprints) usamintra_work.Screenshots
N/A
Quais são tickets relevantes?
#329
scieloorg/xylose#207
Referências
relations.xsd): https://www.crossref.org/schema/relations.xsdtests/xsd/scielo_crossref/crossref4.4.0.xsd)Segurança da informação (NSI.04)
Este PR manipula dados sensíveis ou pessoais (LGPD)?
Este PR altera autenticação, autorização, controle de acesso ou gerenciamento de sessão?
Este PR introduz, atualiza ou remove dependências de terceiros?
Este PR foi validado pelo pipeline de segurança (SonarQube / Trivy)?
Este PR concatena, monta ou executa comandos SQL, HTML ou JavaScript a partir de entrada externa?
Este PR expõe novos endpoints, telas ou serviços?
Algum segredo, senha, chave ou token está sendo adicionado ao código-fonte?