113 lines
4.2 KiB
Python
113 lines
4.2 KiB
Python
from datetime import datetime
|
|
from xml.etree.ElementTree import Element, SubElement, tostring
|
|
from app.db.models import Publication, Researcher
|
|
|
|
ATOM_NS = "http://www.w3.org/2005/Atom"
|
|
DC_NS = "http://purl.org/dc/elements/1.1/"
|
|
EXTRA_NS = "http://example.org/orcid-extra" # namespace para campos extendidos
|
|
|
|
|
|
class SWORDGenerator:
|
|
|
|
@staticmethod
|
|
def generate_feed_xml(researcher: Researcher, publications: list[Publication]) -> bytes:
|
|
feed = Element("feed", {
|
|
"xmlns": ATOM_NS,
|
|
"xmlns:dc": DC_NS,
|
|
"xmlns:extra": EXTRA_NS
|
|
})
|
|
|
|
SubElement(feed, "title").text = f"Publications for {researcher.orcid_id}"
|
|
|
|
author = SubElement(feed, "author")
|
|
SubElement(author, "name").text = researcher.name or "Unknown"
|
|
|
|
SubElement(feed, "updated").text = datetime.utcnow().isoformat() + "Z"
|
|
SubElement(feed, "id").text = f"urn:uuid:{researcher.id}"
|
|
|
|
for pub in publications:
|
|
entry = SubElement(feed, "entry")
|
|
|
|
SubElement(entry, "id").text = f"urn:uuid:{pub.id}"
|
|
SubElement(entry, "updated").text = datetime.utcnow().isoformat() + "Z"
|
|
|
|
# Title
|
|
SubElement(entry, f"{{{DC_NS}}}title").text = pub.title or "Untitled"
|
|
|
|
# Subtitle
|
|
if pub.subtitle:
|
|
SubElement(entry, f"{{{EXTRA_NS}}}subtitle").text = pub.subtitle
|
|
|
|
# DOI
|
|
if pub.doi:
|
|
SubElement(entry, f"{{{DC_NS}}}identifier").text = f"doi:{pub.doi}"
|
|
|
|
# Journal
|
|
if pub.journal:
|
|
SubElement(entry, f"{{{DC_NS}}}source").text = pub.journal
|
|
|
|
# URL
|
|
if pub.url:
|
|
SubElement(entry, f"{{{DC_NS}}}relation").text = pub.url
|
|
|
|
# Short description
|
|
if pub.short_description:
|
|
SubElement(entry, f"{{{DC_NS}}}description").text = pub.short_description
|
|
|
|
# Citation
|
|
if pub.citation_value:
|
|
cit = SubElement(entry, f"{{{EXTRA_NS}}}citation")
|
|
SubElement(cit, "type").text = pub.citation_type or "unknown"
|
|
SubElement(cit, "value").text = pub.citation_value
|
|
|
|
# Language
|
|
if pub.language_code:
|
|
SubElement(entry, f"{{{DC_NS}}}language").text = pub.language_code
|
|
|
|
# Country
|
|
if pub.country:
|
|
SubElement(entry, f"{{{EXTRA_NS}}}country").text = pub.country
|
|
|
|
# External IDs
|
|
if pub.external_ids:
|
|
ext_ids_el = SubElement(entry, f"{{{EXTRA_NS}}}external_ids")
|
|
for ext in pub.external_ids:
|
|
ext_el = SubElement(ext_ids_el, "external_id")
|
|
for k, v in ext.items():
|
|
if isinstance(v, dict) and "value" in v:
|
|
SubElement(ext_el, k).text = v["value"]
|
|
else:
|
|
SubElement(ext_el, k).text = str(v)
|
|
|
|
# Contributors
|
|
if pub.contributors:
|
|
contribs_el = SubElement(entry, f"{{{EXTRA_NS}}}contributors")
|
|
for c in pub.contributors:
|
|
c_el = SubElement(contribs_el, "contributor")
|
|
SubElement(c_el, "name").text = c.get("name")
|
|
SubElement(c_el, "orcid").text = c.get("orcid")
|
|
SubElement(c_el, "role").text = c.get("role")
|
|
|
|
# Date
|
|
if pub.pub_year:
|
|
date_str = str(pub.pub_year)
|
|
if pub.pub_month:
|
|
date_str += f"-{pub.pub_month:02d}"
|
|
if pub.pub_day:
|
|
date_str += f"-{pub.pub_day:02d}"
|
|
SubElement(entry, f"{{{DC_NS}}}date").text = date_str
|
|
|
|
# Type
|
|
if pub.type:
|
|
SubElement(entry, f"{{{DC_NS}}}type").text = pub.type
|
|
|
|
# Status (new / updated / unchanged)
|
|
if hasattr(pub, "status") and pub.status:
|
|
SubElement(entry, f"{{{EXTRA_NS}}}status").text = pub.status
|
|
|
|
# Last modified
|
|
if pub.last_modified:
|
|
SubElement(entry, f"{{{EXTRA_NS}}}last_modified").text = pub.last_modified.isoformat()
|
|
|
|
return tostring(feed, encoding="utf-8", xml_declaration=True)
|