Повний робочий приклад доступний на GitHub:
manage-xmp-in-psd-and-ai-files-python

Вступ

Маркетинг‑команда завантажує 400 PSD‑файлів у вашу платформу активів. Завантаження працює. Пошук – ні, бо жоден файл не містить ключових слів, у половини відсутнє повідомлення про авторські права, а імена дизайнерів живуть лише у якомусь електронному листі. Виправленням не стане ще один лист. Управління XMP – це можливість GroupDocs.Metadata для Python через .NET, яка читає та записує пакет метаданих, вбудований у файли Photoshop PSD та Illustrator AI, що означає, що дані про власність і пошук можуть зберігатися безпосередньо у файлах.

XMP – це XML‑пакет всередині бінарного контейнера, організований у схеми: Dublin Core для полів, зрозумілих усім системам, схема Photoshop для редакційного контексту, XmpBasic для ідентифікації інструменту. Ручне розбір PSD, щоб дістатися до цього пакету, дійсно складне. За допомогою класу Metadata це лише три пошуки атрибутів, і той самий код працює і з AI‑файлами.

У цьому підручнику розглядається повний цикл у чотирьох кроках: знімок усього пакету, читання потрібних схем, запис авторських прав та автора, і тегування ключових слів для пошуку. Кожен фрагмент коду взятий із робочого репозиторію, який перевіряє, що записані значення зберігаються.

Передумови

Перед початком переконайтеся, що у вас є:

  • Python 3 з pip
  • GroupDocs.Metadata для Python через .NET (репозиторій фіксує версію 26.5)
  • PSD або AI файл для експериментів

Встановлення

pip install groupdocs-metadata-net==26.5

Крок 1 – Знімок усього пакету XMP

Почніть із перегляду всього, що несе файл. Знімок проходить кореневий пакет, кожну зареєстровану схему і, нарешті, обшукує дерево властивостей на предмет нестандартних елементів, збираючи все в один плоский словник.

result = {}

def put(props, prop):
    value = (str(prop.interpreted_value) if prop.interpreted_value is not None
             else (str(prop.value) if prop.value is not None else ""))
    props[prop.name] = value

with Metadata("campaign-hero.psd") as metadata:
    root = metadata.get_root_package()
    xmp = getattr(root, "xmp_package", None)
    if xmp is not None:
        for p in xmp:                                  # root packet properties
            put(result, p)
        schemes = xmp.schemes
        for scheme in (schemes.dublin_core, schemes.xmp_basic, schemes.photoshop,
                       schemes.camera_raw, schemes.paged_text,
                       schemes.xmp_dynamic_media, schemes.xmp_media_management):
            if scheme is None:
                continue
            for p in scheme:
                put(result, p)
    for p in metadata.find_properties(lambda p: p.name is not None):
        if p.name not in result:                       # catch custom packets
            put(result, p)

Ключові моменти:

  • interpreted_value перш за все: дати та перерахування приходять у людському вигляді, а не у вигляді сирих даних.
  • Сім схем плюс обшук: завершальний прохід find_properties ловить пакети виробників, які не охоплюються іменованими схемами.
  • Одне відкриття файлу: весь знімок виконується в одному контексті Metadata, що важливо при масовому внесенні.

Підказка: індексуйте цей словник під час внесення, і більшість подальших запитів до метаданих стануть пошуком у словнику замість читання файлів.

Яку схему XMP має читати моя інтеграція першою?

Починайте з Dublin Core. Його дев’ять полів dc: містять назву, автора, права та теми, які узгоджуються у більшості DAM‑систем, пошукових індексів і перевірок ліцензування, і їх однаково експонує як PSD, так і AI. Другим читайте схему Photoshop для редакційного контексту, наприклад City, Credit та DateCreated. Повний обшук пакету залиште для завдань внесення, які мають захопити все.

Крок 2 – Читання схем, що відповідають на реальні питання

Для коду, що виконується за запитом, обмежте читання однією схемою. Dublin Core відповідає на питання про власність і пошук:

dc_fields = {}
with Metadata("campaign-hero.psd") as metadata:
    xmp = getattr(metadata.get_root_package(), "xmp_package", None)
    dc = xmp.schemes.dublin_core if xmp is not None else None
    if dc is not None:
        for p in dc:
            dc_fields[p.name] = (str(p.interpreted_value)
                                 if p.interpreted_value is not None else
                                 str(p.value) if p.value is not None else "")

print(dc_fields.get("dc:rights", "<no rights recorded>"))

Схема Photoshop працює так само через типізовані властивості: ps.color_mode, ps.icc_profile, ps.city, ps.country, ps.date_created, ps.caption_writer, ps.credit і ps.source, кожна читається з захистом від None. Це ті поля, які використовують Bridge, Lightroom і фільтри пошуку DAM для файлів Adobe.

Зверніть увагу, що відбувається з файлами без XMP: захисти повертають порожній словник, а не виключення. Свіжоекспортовані активи часто потрапляють у таку ситуацію, тому зберігайте таку поведінку у вашій інтеграції.

Ті ж три запити працюють і з Illustrator‑файлами. Замініть campaign-hero.psd на brand-mark.ai – нічого іншого не зміниться, що робить один шлях коду реалістичним для змішаних архівів Adobe. На практиці свіжий AI‑експорт зазвичай містить менше заповнених схем, ніж збереження Photoshop, тому шлях порожнього словника використовується частіше.

Крок 3 – Запис авторських прав та автора

Тепер шлях запису. Маркування власності торкається трьох полів, щоб кожен читач бачив одну й ту ж ідентичність: dc:rights – юридичне повідомлення, dc:creator – упорядкований список, і xmp:CreatorTool – інструменти, які читають схему XmpBasic замість Dublin Core. Колись я втратив половину дня, бо банер ліцензування показував «Unknown author» у активах, які дизайнери клялися, що позначені; значення були в dc:creator, а інструмент читав лише xmp:CreatorTool. Запис обох полів усунув цей тип помилки.

with Metadata("campaign-hero.psd") as metadata:
    root = metadata.get_root_package()
    xmp = getattr(root, "xmp_package", None)
    if xmp is None:                          # file has no XMP at all
        root.xmp_package = XmpPacketWrapper()
        xmp = root.xmp_package
    if xmp.schemes.dublin_core is None:
        xmp.schemes.dublin_core = XmpDublinCorePackage()

    dc = xmp.schemes.dublin_core
    dc.set_rights("(C) 2026 GroupDocs Sample")
    dc.set("dc:creator", XmpArray.from_(["Digital Asset Team"],
                                        XmpArrayType.ORDERED))

    if xmp.schemes.xmp_basic is None:
        xmp.schemes.xmp_basic = XmpBasicPackage()
    xmp.schemes.xmp_basic.creator_tool = "Digital Asset Team"

    metadata.save("campaign-hero-stamped.psd")

Ключові моменти:

  • Захисти створюють відсутні шари: XmpPacketWrapper і XmpDublinCorePackage створюються за потребою, тому запис працює і у файлах без XMP.
  • Упорядкований масив для авторів: порядок авторів має значення, тому список авторів використовує упорядкований XmpArray.
  • Збереження у новий шлях: вихідний файл залишається незмінним, що є правильним за замовчуванням для кроків експорту.

Крок 4 – Тегування ключових слів для пошуку

dc:subject – це «мішок» ключових слів, який індексує DAM. Запис замінює весь мішок одним викликом:

with Metadata("campaign-hero.psd") as metadata:
    root = metadata.get_root_package()
    xmp = getattr(root, "xmp_package", None)
    if xmp is None:
        root.xmp_package = XmpPacketWrapper()
        xmp = root.xmp_package
    if xmp.schemes.dublin_core is None:
        xmp.schemes.dublin_core = XmpDublinCorePackage()

    xmp.schemes.dublin_core.set(
        "dc:subject",
        XmpArray.from_(["landscape", "sunset", "commercial"],
                       XmpArrayType.UNORDERED))
    metadata.save("campaign-hero-tagged.psd")

Ключові слова використовують масив UNORDERED, бо порядок не має значення для індексатора. Оскільки set замінює існуючий мішок, спочатку прочитайте поточні ключові слова і об’єднайте їх у Python, коли потрібне додавання, а не заміна.

Щоб перевірити будь‑який запис, запустіть читач Кроку 2 ще раз для вихідного файлу. Репозиторій автоматизує саме це: він перечитує свої виходи і стверджує, що рядок авторських прав і перше ключове слово залишаються в збережених байтах.

Реальні застосування

Внесення в DAM

Запускайте знімок Кроку 1 для кожного вхідного файлу і зберігайте словник разом із записом активу. Пошук, дедуплікація та перевірки прав потім виконуються проти вашої бази даних, а не шляхом повторного відкриття бінарних файлів. Знімок невеликого зразка PSD у репозиторії вже повертає здоровий набір властивостей за один прохід, і той самий виклик зберігає свою форму, коли вхід стає папкою з тисячами файлів.

Забезпечення ліцензування

Перед тим, як актив потрапить у клієнтський портал, вимагайте непорожнє dc:rights. Файли, які не проходять, автоматично отримують обробку Кроку 3, тому нічого не залишиться без повідомлення.

Пакетне повторне тегування

Коли таксономія змінюється, читайте dc:subject кожного файлу, зіставляйте старі терміни з новими у Python і записуйте об’єднаний мішок назад за допомогою Кроку 4. І PSD, і AI архіви проходять один і той же цикл. Не потрібен Photoshop.

Кращі практики та поради

  • Вважавайте порожні файли нормою: файли без XMP – це рутина, а не помилки; патерн раннього повернення підтримує безперервність конвеєрів.
  • Об’єднуйте перед записом ключових слів: set замінює dc:subject, тому додаткове тегування означає читання, розширення, запис.
  • Записуйте ідентичність у обох схемах: поєднання dc:creator з xmp:CreatorTool забезпечує узгодженість читачів Dublin Core і XmpBasic.
  • Перевіряйте записи повторним читанням: перечитування після збереження недороге і миттєво виявляє несподівані проблеми контейнера.
  • Ліцензія для продакшн: режим оцінки виконує все, що показано тут; використайте ліцензію перед маркуванням реальних клієнтських активів.

Висновок

Читання та запис XMP у файлах Adobe зводиться до трьох кроків: отримати пакет через get_root_package(), захистити потрібну схему і читати або записувати типізовані значення. Виконавши ці кроки, ви створили повний цикл у цьому підручнику – від знімка пакету до читання схем, маркування авторських прав і тегування ключових слів, використовуючи один і той же код для PSD та AI файлів.

Готові впровадити це у ваш проєкт? Ось кілька наступних кроків:

Додаткові ресурси

Питання щодо вашого XMP‑робочого процесу? Запитайте на support forum.