From e0c6872cf40896c7be36b11dcc744620f10adf1d Mon Sep 17 00:00:00 2001
From: Norbert Preining <norbert@preining.info>
Date: Mon, 2 Sep 2019 13:46:59 +0900
Subject: Initial commit

---
 macros/latex/contrib/hyperxmp/hyperxmp.dtx | 5055 ++++++++++++++++++++++++++++
 1 file changed, 5055 insertions(+)
 create mode 100644 macros/latex/contrib/hyperxmp/hyperxmp.dtx

(limited to 'macros/latex/contrib/hyperxmp/hyperxmp.dtx')

diff --git a/macros/latex/contrib/hyperxmp/hyperxmp.dtx b/macros/latex/contrib/hyperxmp/hyperxmp.dtx
new file mode 100644
index 0000000000..a5aa24a146
--- /dev/null
+++ b/macros/latex/contrib/hyperxmp/hyperxmp.dtx
@@ -0,0 +1,5055 @@
+% \iffalse meta-comment
+%
+% Copyright (C) 2019 by Scott Pakin <scott+hyxmp@pakin.org>
+% -------------------------------------------------------
+%
+% This file may be distributed and/or modified under the
+% conditions of the LaTeX Project Public License, either version 1.3c
+% of this license or (at your option) any later version.
+% The latest version of this license is in:
+%
+%    http://www.latex-project.org/lppl.txt
+%
+% and version 1.3c or later is part of all distributions of LaTeX
+% version 2008/05/04 or later.
+%
+% \fi
+%
+% \iffalse
+%<*driver>
+\ProvidesFile{hyperxmp.dtx}
+%</driver>
+%<package>\NeedsTeXFormat{LaTeX2e}[1999/12/01]
+%<package>\ProvidesPackage{hyperxmp}
+%<*package>
+    [2019/04/05 v4.1 Store hyperref metadata in XMP format]
+%</package>
+%
+%<*driver>
+\bgroup
+  \catcode`\&=11
+  \gdef\levelchar{&}
+\egroup
+\documentclass{ltxdoc}
+\usepackage{graphicx}
+\usepackage{color}
+\usepackage{tocbibind}
+\usepackage{microtype}
+\usepackage{needspace}
+\usepackage{varioref}
+\usepackage{alltt}
+\usepackage{multicol}
+\usepackage{makeidx}
+\usepackage[utf8]{inputenc}
+\usepackage{hyperxmp}
+\usepackage[unicode,bookmarksopen,bookmarksopenlevel=2,bookmarksnumbered]{hyperref}
+\EnableCrossrefs
+\CodelineIndex
+\RecordChanges
+
+% Specify this document's metadata.
+\GetFileInfo{hyperxmp.dtx}
+\title{The \pkgname{hyperxmp} package\thanks{This document
+  corresponds to \pkgname{hyperxmp}~\fileversion, dated \filedate.}}
+\author{Scott Pakin \\ \texttt{scott+hyxmp@pakin.org}}
+\makeatletter
+\edef\versionnumber{\expandafter\@gobble\fileversion}  % Drop the "v" in the file version.
+\makeatother
+\hypersetup{%
+  pdfauthor={Scott Pakin},
+  pdftitle={The hyperxmp package},
+  pdfsubject={LaTeX2e support for XMP metadata},
+  pdfkeywords={LaTeX, embedded metadata, XMP, PDF, copyright, license, comments},
+  pdfcopyright={Copyright (C) 2019, Scott Pakin},
+  pdflicenseurl={http://www.latex-project.org/lppl/},
+  pdfcaptionwriter={Scott Pakin},
+  pdfcontactemail={scott+hyxmp@pakin.org},
+  pdfcontacturl={http://www.pakin.org/\xmptilde scott/},
+  pdfversionid={\versionnumber},
+  pdflang={en-US},
+  pdfurl={http://mirror.ctan.org/macros/latex/contrib/hyperxmp/hyperxmp.pdf},
+  baseurl={http://mirror.ctan.org/macros/latex/contrib/hyperxmp/}
+}
+
+\begin{document}
+  \DocInput{hyperxmp.dtx}
+  \Needspace{10\baselineskip}
+  \phantomsection\addcontentsline{toc}{section}{Change History}
+  \PrintChanges
+  \makeatletter
+  \let\orig@index@prologue=\index@prologue
+  \def\index@prologue{%
+    \phantomsection\addcontentsline{toc}{section}{Index}
+    \orig@index@prologue
+  }%
+  \makeatother
+  \Needspace{12\baselineskip}
+  \PrintIndex
+\end{document}
+%</driver>
+% \fi
+%
+% \CheckSum{2095}
+%
+% \CharacterTable
+%  {Upper-case    \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
+%   Lower-case    \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z
+%   Digits        \0\1\2\3\4\5\6\7\8\9
+%   Exclamation   \!     Double quote  \"     Hash (number) \#
+%   Dollar        \$     Percent       \%     Ampersand     \&
+%   Acute accent  \'     Left paren    \(     Right paren   \)
+%   Asterisk      \*     Plus          \+     Comma         \,
+%   Minus         \-     Point         \.     Solidus       \/
+%   Colon         \:     Semicolon     \;     Less than     \<
+%   Equals        \=     Greater than  \>     Question mark \?
+%   Commercial at \@     Left bracket  \[     Backslash     \\
+%   Right bracket \]     Circumflex    \^     Underscore    \_
+%   Grave accent  \`     Left brace    \{     Vertical bar  \|
+%   Right brace   \}     Tilde         \~}
+%
+%
+% \changes{v1.0}{2006/05/14}{Initial version}
+% \changes{v2.0}{2012/08/02}{Heiko Oberdiek's major rewrite of the code
+%   to better support native-Unicode \string\TeX\ implementations
+%   (\string\XeTeX\ and \string\LuaTeX)}
+% \changes{v2.0}{2012/08/26}{Added support for the \protect\acro{XMP} Basic
+%   schema and miscellaneous other bits of metadata}
+% \changes{v1.2}{2010/06/04}{Added support for the \protect\XeTeX\ backend
+%   (\texttt{xdvipdfmx})}
+% \changes{v1.2}{2010/06/07}{Added support for the Photoshop schema}
+% \changes{v2.2}{2010/12/06}{Added support for the \protect\acro{IPTC} Photo Metadata schema}
+% \changes{v2.4}{2013/12/21}{Added support for the \protect\acro{PDF/A}
+%   Identification schema, as requested by Florian Breitwieser}
+% \changes{v2.5}{2014/06/19}{Enabled ``\texttt{\string\string\string\_}''
+%   to work within email addresses, as requested by Leonid Sinev}
+% \changes{v2.6}{2014/09/24}{Added support for a new \protect\optname{pdfdate}
+%   key to explicitly specify the document date (and optionally time)}
+% \changes{v2.9}{2016/04/25}{Force inclusion of \protect\xmpprop{dc:creator},
+%   \protect\xmpprop{dc:title}, and \protect\xmpprop{dc:description}---even if
+%   empty---when \protect\pkgname{hyperref} is loaded with the
+%   \protect\optname{pdfa} option (suggested by Leonid Sinev)}
+% \changes{v2.9}{2016/04/26}{Introduced the \protect\optname{pdftype}
+%   package option, which enables an author to specify the type of
+%   document being produced}
+% \changes{v3.0}{2016/07/02}{Made the code compatible with \string\LuaTeX~0.85.
+%   Thanks to Robert Schlicht, Leonid Sinev, and David Carlisle for bug
+%   reports and to Leonid Sinev for helping test the new
+%   \protect\pkgname{hyperxmp} code}
+% \changes{v3.4}{2017/11/04}{Use \protect\pkgname{ifmtarg} to test for
+%   empty arguments, including non-empty but all spaces}
+% \changes{v4.0}{2019/03/14}{Include all metadata within a single
+%   \protect\xmpterm{rdf:Description} block}
+% \changes{v4.1}{2019/04/05}{Updated the documentation to refer to
+%   \protect\cs{pdfnumpages} by its correct name.  Thanks to Volker RW Schaa
+%   for catching the discrepancy}
+%
+% ^^A \GetFileInfo{hyperxmp.dtx}
+%
+% \DoNotIndex{\,,\&,\ ,\!,\",\#,\(,\),\*,\<,\>,\\,\^,\~,\^,\_}
+% \DoNotIndex{\@cons,\@empty,\@firstofone,\@firstoftwo,\@gobble,\@gobbletwo}
+% \DoNotIndex{\@ifpackageloaded,\@ifundefined,\@nil,\@secondoftwo}
+% \DoNotIndex{\@tempcnta,\@tempcntb,\MessageBreak,\advance,\afterassignment}
+% \DoNotIndex{\aftergroup,\begin,\begingroup,\bgroup,\catcode,\csname,\def}
+% \DoNotIndex{\divide,\edef,\egroup,\else,\end,\endcsname,\endgroup}
+% \DoNotIndex{\expandafter,\fi,\futurelet,\g@addto@macro,\gdef,\global,\if}
+% \DoNotIndex{\ifcase,\ifnum,\ifx,\immediate,\lccode,\let,\loop,\lowercase}
+% \DoNotIndex{\multiply,\newcommand,\noexpand,\or,\relax,\repeat,\space}
+% \DoNotIndex{\string,\the,\toks,\uccode,\uppercase,\usepackage,\xdef}
+%
+% ^^A  Define a few logical styles.
+% \DeclareRobustCommand{\term}[1]{#1\SortIndex{#1}{#1}}
+% \DeclareRobustCommand{\pkgname}[1]{\mbox{\textsf{#1}}\SortIndex{#1}{\textsf{#1}}}
+% \makeatletter
+% \DeclareRobustCommand{\xmpprop}[2][]{^^A   XMP property
+%   \def\xmppropopt{#1}^^A
+%   \ifx\xmppropopt\@empty
+%     \mbox{\textsf{#2}}^^A
+%   \else
+%     \mbox{\textsf{#2}}.\mbox{\textsf{#1}}^^A
+%     \SortIndex{#1}{\textsf{#1}}^^A
+%   \fi
+%   \SortIndex{#2}{\textsf{#2}}^^A
+%   \index{properties, \acrostyle{XMP}&#2=\textsf{#2}}^^A
+% }
+% \DeclareRobustCommand{\xmpterm}[1]{^^A     All other XMP terms
+%   \mbox{\textsf{#1}}^^A
+%   \SortIndex{#1}{\textsf{#1}}^^A
+% }
+% \makeatother
+% \index{XMP=\acrostyle  {XMP}&properties|see{properties, \acrostyle{XMP}}}
+% \DeclareRobustCommand{\pdfterm}[1]{\mbox{\textsf{#1}}\SortIndex{#1}{\textsf{#1}}}
+% \DeclareRobustCommand{\cmdname}[1]{\mbox{\texttt{#1}}\SortIndex{#1}{\texttt{#1}}}
+% \DeclareRobustCommand{\optname}[1]{^^A
+%   \mbox{\textsf{#1}}^^A
+%   \SortIndex{#1}{\textsf{#1} (option)}^^A
+%   \index{options&#1=\textsf{#1}}^^A
+% }
+% ^^A  \moptname is the same as \optname but additionally typesets the
+% ^^A  option name in the margin.
+% \DeclareRobustCommand{\moptname}[1]{^^A
+%   \optname{#1}^^A
+%   \marginpar{\raggedleft\strut\mbox{\textsf{#1}}}^^A
+% }
+% \DeclareRobustCommand{\acrostyle}[1]{\textsc{\MakeLowercase{#1}}}
+% \DeclareRobustCommand{\acro}[1]{^^A
+%   \mbox{\acrostyle{#1}}^^A
+%   \SortIndex{#1}{\acrostyle{#1}}^^A
+% }
+% \newcounter{note}
+% \newcommand{\usagenote}[1]{^^A
+%   \refstepcounter{note}^^A
+%   \paragraph{Note~\thenote: #1}%
+% }
+%
+% ^^A  Define some other shortcut macros.
+% \DeclareRobustCommand{\tex}{^^A
+%   \texorpdfstring{\TeX\SortIndex{TeX}{\TeX}}{TeX}^^A
+% }
+% \DeclareRobustCommand{\XeTeXlogo}{^^A
+%   X\lower0.5ex\hbox{\kern-.15em\reflectbox{E}}\kern-0.1667em\TeX
+% }
+% \DeclareRobustCommand{\XeTeX}{^^A
+%   \texorpdfstring{\XeTeXlogo\SortIndex{XeTeX}{\XeTeXlogo}}{XeTeX}^^A
+% }
+% \DeclareRobustCommand{\XeLaTeXlogo}{^^A
+%   X\lower0.5ex\hbox{\kern-.15em\reflectbox{E}}\kern-0.1667em\LaTeX
+% }
+% \DeclareRobustCommand{\XeLaTeX}{^^A
+%   \texorpdfstring{\XeLaTeXlogo\SortIndex{XeLaTeX}{\XeLaTeXlogo}}{XeLaTeX}^^A
+% }
+% \DeclareRobustCommand{\LuaTeXlogo}{Lua\TeX}
+% \DeclareRobustCommand{\LuaTeX}{^^A
+%   \texorpdfstring{\LuaTeXlogo\SortIndex{LuaTeX}{\LuaTeXlogo}}{LuaTeX}^^A
+% }
+% \DeclareRobustCommand{\LuaLaTeXlogo}{Lua\LaTeX}
+% \DeclareRobustCommand{\LuaLaTeX}{^^A
+%   \texorpdfstring{\LuaLaTeXlogo\SortIndex{LuaLaTeX}{\LuaLaTeXlogo}}{LuaLaTeX}^^A
+% }
+% \DeclareRobustCommand{\pdfTeXlogo}{pdf\TeX}
+% \DeclareRobustCommand{\pdfTeX}{^^A
+%   \texorpdfstring{\pdfTeXlogo\SortIndex{pdfTeX}{\pdfTeXlogo}}{pdfTeX}^^A
+% }
+% \DeclareRobustCommand{\pdfLaTeXlogo}{pdf\LaTeX}
+% \DeclareRobustCommand{\pdfLaTeX}{^^A
+%   \texorpdfstring{\pdfLaTeXlogo\SortIndex{pdfLaTeX}{\pdfLaTeXlogo}}{pdfLaTeX}^^A
+% }
+% \DeclareRobustCommand{\Dvips}{^^A
+%   \texorpdfstring{Dvips\SortIndex{dvips}{\texttt{dvips}}}{Dvips}^^A
+% }
+% \DeclareRobustCommand{\Lua}{^^A
+%   Lua\index{Lua}^^A
+% }
+%
+% ^^A  Define an environment just like macro but for Lua functions.
+% \makeatletter
+% \newenvironment{luafunc}{^^A
+%   \begingroup
+%     \catcode`\_=11
+%     \def\PrintMacroName##1{\strut\MacroFont\string##1\ }^^A
+%     \def\SpecialIndex@##1##2{^^A
+%       \@bsphack
+%       \special@index{\string##1\actualchar
+%         \string\verb\quotechar*\verbatimchar##1\verbatimchar##2}^^A
+%       \@esphack
+%     }^^A
+%     \begin{macro}^^A
+% }{^^A
+%     \end{macro}^^A
+%   \endgroup
+% }
+% \makeatother
+%
+% ^^A  Pack figures a bit tighter onto the page.
+% \renewcommand{\floatpagefraction}{0.8}
+%
+% ^^A  Help \pageref refer to arbitrary content.
+% \newcounter{pagelabel}
+%
+% \maketitle
+% \sloppy
+%
+% \begin{abstract}
+%   \pkgname{hyperxmp} makes it easy for an author to include \acro{XMP}
+%   metadata in a \acro{PDF} document produced by \LaTeX\@.  \pkgname{hyperxmp}
+%   integrates seamlessly with \pkgname{hyperref} and requires virtually
+%   no modifications to a document that already specifies document
+%   metadata through \pkgname{hyperref}'s mechanisms.
+% \end{abstract}
+%
+%
+% \section{Introduction}
+%
+% Adobe Systems, Inc.\ has been promoting
+% \acro{XMP}~\cite{Adobe2012:XMP}---eXtensible Metadata Platform---as a
+% standard way to include metadata within a document.  The idea behind
+% \acro{XMP} is that it is an \acro{XML}-based description of various
+% document attributes and is embedded as uncompressed, unencoded text
+% within the document it describes.  By storing the metadata this way it
+% is independent of the document's file format.  That is, regardless of
+% whether a document is in \acro{PDF}, \acrostyle{JPEG},
+% \acrostyle{HTML}, or any other format, it is trivial for a program (or
+% human) to locate, extract, and---using any standard \acro{XML}
+% parser---process the embedded \acro{XMP} metadata.
+%
+% As of this writing there are few tools that actually do process
+% \acro{XMP}\@.  However, it is easy to imagine future support existing
+% in file browsers for displaying not only a document's filename but
+% also its title, list of authors, description, and other metadata.
+%
+% \paragraph{This is too abstract!  Give me an example.}
+% Consider a \LaTeX\ document with three authors: Jack Napier, Edward
+% Nigma, and Harvey Dent.  The generated \acro{PDF} file will contain,
+% among other information, the following stanza of \acro{XMP} code
+% embedded within it:
+%
+% \begin{verbatim}
+%    <dc:creator>
+%      <rdf:Seq>
+%        <rdf:li>Jack Napier</rdf:li>
+%        <rdf:li>Edward Nigma</rdf:li>
+%        <rdf:li>Harvey Dent</rdf:li>
+%      </rdf:Seq>
+%    </dc:creator>
+% \end{verbatim}
+%
+% In the preceding code, the |dc| namespace refers to the
+% \href{http://purl.org/DC/}{Dublin Core schema}, a collection of
+% metadata properties.  The \xmpprop{dc:creator} property surrounds the
+% list of authors.  The \textsf{rdf} namespace is the
+% \href{http://www.w3.org/RDF/}{Resource Description Framework}, which
+% defines \xmpterm{rdf:Seq} as an ordered list of values.  Each author
+% is represented by an individual list item (\xmpterm{rdf:li}), making
+% it easy for an \acro{XML} parser to separate the authors' names.
+%
+% Remember that \acro{XMP} code is stored as \emph{metadata}.  It does
+% not appear when viewing or printing the \acro{PDF} file.  Rather, it
+% is intended to make it easy for applications to identify and
+% categorize the document.
+%
+% \paragraph{What metadata does \textsf{hyperxmp} process?}
+% \pkgname{hyperxmp} knows how to embed all of the following types of
+% metadata within a document:
+%
+% \label{page:begin-metadata-list}
+% \begin{itemize} \raggedright
+%   \item address of primary author
+%     (\xmpprop[CiAdrExtadr]{Iptc4xmpCore:CreatorContactInfo},
+%     \xmpprop[CiAdrCity]{Iptc4xmpCore:CreatorContactInfo},
+%     \xmpprop[CiAdrRegion]{Iptc4xmpCore:CreatorContactInfo},
+%     \xmpprop[CiAdrPcode]{Iptc4xmpCore:CreatorContactInfo}, and
+%     \xmpprop[CiAdrCtry]{Iptc4xmpCore:CreatorContactInfo})
+%   \item author(s) (\xmpprop{dc:creator})
+%   \item base \acro{URL} for relative references (\xmpprop{xmp:BaseURL})
+%   \item book edition (\xmpprop{prism:bookEdition})
+%   \item copyright (\xmpprop{dc:rights} and \xmpprop{xmpRights:Marked})
+%   \item date (\xmpprop{dc:date}, \xmpprop{xmp:CreateDate},
+%     \xmpprop{xmp:ModifyDate}, and \xmpprop{xmp:MetadataDate})
+%   \item \acro{DOI} (\xmpprop{prism:doi})
+%   \item email address(es) of primary author (\xmpprop[CiEmailWork]{Iptc4xmpCore:CreatorContactInfo})
+%   \item file format (\xmpprop{dc:format})
+%   \item file name of main \LaTeX\ source file (\xmpprop{dc:source})
+%   \item file size in bytes (\xmpprop{prism:byteCount})
+%   \item \acro{ISBN} (\xmpprop{prism:isbn})
+%   \item \acro{ISSN}---both print (\xmpprop{prism:issn}) and electronic (\xmpprop{prism:eIssn})
+%   \item issue number of parent publication (\xmpprop{prism:number})
+%   \item keywords (\xmpprop{pdf:Keywords} and \xmpprop{dc:subject})
+%   \item language used (\xmpprop{dc:language})
+%   \item license \acro{URL} (\xmpprop{xmpRights:WebStatement})
+%   \item metadata writer (\xmpprop{photoshop:CaptionWriter})
+%   \item page count (\xmpprop{prism:pageCount})
+%   \item page range(s) (\xmpprop{prism:pageRange})
+%   \item \acro{PDF} version (\xmpprop{pdf:PDFVersion})
+%   \item \acro{PDF}-generating tool (\xmpprop{pdf:Producer} and \xmpprop{xmp:CreatorTool})
+%   \item \acro{PDF/A} compliance level and version (\xmpprop{pdfaid:part} and \xmpprop{pdfaid:conformance})
+%   \item position/title of primary author (\xmpprop{photoshop:AuthorsPosition})
+%   \item publication name of parent publication (\xmpprop{prism:publicationName})
+%   \item publisher of the document (\xmpprop{dc:publisher})
+%   \item summary (\xmpprop{dc:description})
+%   \item subtitle (\xmpprop{prism:subtitle})
+%   \item telephone number(s) of primary author (\xmpprop[CiTelWork]{Iptc4xmpCore:CreatorContactInfo})
+%   \item title (\xmpprop{dc:title})
+%   \item type of document (\xmpprop{dc:type})
+%   \item type of parent publication (\xmpprop{prism:aggregationType})
+%   \item \acro{URL} of the document (\xmpprop{prism:url})
+%   \item \acro{URL}(s) of the primary author (\xmpprop[CiUrlWork]{Iptc4xmpCore:CreatorContactInfo})
+%   \item \acro{UUID} for the document (\xmpprop{xmpMM:DocumentID})
+%   \item \acro{UUID} for the document instance (\xmpprop{xmpMM:InstanceID})
+%   \item version identifier for the document (\xmpprop{xmpMM:VersionID})
+%   \item volume number of parent publication (\xmpprop{prism:volume})
+% \end{itemize}
+% \label{page:end-metadata-list}
+%
+% \noindent
+% More types of metadata may be added in a future release.
+%
+% \paragraph{How does \textsf{hyperxmp} compare to the \textsf{xmpincl}
+% package?}
+% The short answer is that \pkgname{xmpincl} is more flexible but
+% \pkgname{hyperxmp} is easier to use.  With \pkgname{xmpincl}, the
+% author manually constructs a file of arbitrary \acro{XMP} data and the
+% package merely embeds it within the generated \acro{PDF} file.  With
+% \pkgname{hyperxmp}, the author specifies values for various predefined
+% metadata types and the package formats those values as \acro{XMP} and embeds
+% the result within the generated \acro{PDF} file.
+%
+% \pkgname{xmpincl} can embed \acro{XMP} only when running under \pdfLaTeX\ and
+% only when in \acro{PDF}-generating mode.  \pkgname{hyperxmp} additionally
+% works with a few other \acro{PDF}-producing \LaTeX\ backends.
+%
+% \pkgname{hyperxmp} and \pkgname{xmpincl} can complement each other.
+% An author may want to use \pkgname{hyperxmp} to produce a basic set of
+% \acro{XMP} code, then extract the \acro{XMP} code from the \acro{PDF} file with a text
+% editor, augment the \acro{XMP} code with any metadata not supported by
+% \pkgname{hyperxmp}, and use \pkgname{xmpincl} to include the modified
+% \acro{XMP} code in the \acro{PDF} file.
+%
+% \section{Usage}
+%
+% \pkgname{hyperxmp} works by postprocessing some of the package options
+% honored by \pkgname{hyperref}.  To use \pkgname{hyperxmp}, merely put
+% a |\usepackage{hyperxmp}| in your document's preamble.  That line can
+% appear anywhere before the \pkgname{hyperref} \acro{PDF} options are
+% specified (i.e.,~with either |\usepackage[|\dots|]{hyperref}| or
+% |\hypersetup{|\dots|}|).  \pkgname{hyperxmp} will construct its
+% \acro{XMP} data using the following \pkgname{hyperref} options:
+%
+% \begin{multicols}{3}
+%   \raggedcolumns
+%   \begin{itemize}
+%   \item \optname{baseurl}
+%   \item \optname{pdfauthor}
+%   \item \optname{pdfcreationdate}
+%   \item \optname{pdfkeywords}
+%   \item \optname{pdflang}
+%   \item \optname{pdfmoddate}
+%   \item \optname{pdfproducer}
+%   \item \optname{pdfsubject}
+%   \item \optname{pdftitle}
+%   \end{itemize}
+% \end{multicols}
+%
+% \noindent
+% \mbox{}\label{page:begin-new-options}
+% \pkgname{hyperxmp} instructs \pkgname{hyperref} also to accept the
+% following options, which have meaning only to \pkgname{hyperxmp}:
+%
+% \begin{multicols}{3}
+%   \raggedcolumns
+%   \begin{itemize}
+%   \item \optname{pdfaconformance}
+%   \item \optname{pdfapart}
+%   \item \optname{pdfauthortitle}
+%   \item \optname{pdfbookedition}
+%   \item \optname{pdfbytes}
+%   \item \optname{pdfcaptionwriter}
+%   \item \optname{pdfcontactaddress}
+%   \item \optname{pdfcontactcity}
+%   \item \optname{pdfcontactcountry}
+%   \item \optname{pdfcontactemail}
+%   \item \optname{pdfcontactphone}
+%   \item \optname{pdfcontactpostcode}
+%   \item \optname{pdfcontactregion}
+%   \item \optname{pdfcontacturl}
+%   \item \optname{pdfcopyright}
+%   \item \optname{pdfdate}
+%   \item \optname{pdfdocumentid}
+%   \item \optname{pdfdoi}
+%   \item \optname{pdfeissn}
+%   \item \optname{pdfinstanceid}
+%   \item \optname{pdfisbn}
+%   \item \optname{pdfissn}
+%   \item \optname{pdfissuenum}
+%   \item \optname{pdflicenseurl}
+%   \item \optname{pdfmetadate}
+%   \item \optname{pdfmetalang}
+%   \item \optname{pdfnumpages}
+%   \item \optname{pdfpagerange}
+%   \item \optname{pdfpublication}
+%   \item \optname{pdfpublisher}
+%   \item \optname{pdfpubtype}
+%   \item \optname{pdfsource}
+%   \item \optname{pdfsubtitle}
+%   \item \optname{pdftype}
+%   \item \optname{pdfurl}
+%   \item \optname{pdfversionid}
+%   \item \optname{pdfvolumenum}
+%   \end{itemize}
+% \end{multicols}
+% \label{page:end-new-options}
+%
+%
+% \subsection{Option descriptions}
+%
+% The document title is specified as normal for \pkgname{hyperref} with
+% \moptname{pdftitle}, but see Note~\ref{note:multilingual} on
+% page~\pageref{note:multilingual} for instructions on how to specify a
+% title in multiple languages.  \pkgname{hyperxmp} introduces a
+% complementary \moptname{pdfsubtitle} option:
+%
+% \begin{verbatim}
+%   pdftitle={Frankenstein},
+%   pdfsubtitle={The Modern Prometheus},
+% \end{verbatim}
+%
+% Unfortunately, the subtitle can appear in only one language.  It
+% assumed to be the same language as the document language
+% (\optname{pdflang}) but can be overridden by preceding the text with a
+% bracketed \acro{ISO} \mbox{639-1} two-letter language code and an
+% optional \acro{ISO} \mbox{3166-1} two-letter region code.  See the
+% example below for \optname{pdfpublication}.
+%
+% \Needspace{6\baselineskip}
+% \moptname{pdfauthortitle} indicates the primary author's position or
+% title.  \moptname{pdfcaptionwriter} specifies the name of the person
+% who added the metadata to the document.  The next eight items describe
+% how to contact the person or institution responsible for the document
+% (the ``contact'').  \moptname{pdfcontactaddress} is the contact's
+% street address and can include the institution name if the contact is
+% an institution; \moptname{pdfcontactcity} is the contact's city;
+% \moptname{pdfcontactcountry} is the contact's country;
+% \moptname{pdfcontactemail} is the contact's email address (or
+% multiple, comma-separated email addresses); \moptname{pdfcontactphone}
+% is the contact's telephone number (or multiple, comma-separated
+% telephone numbers); \moptname{pdfcontactpostcode} is the contact's
+% postal code; \moptname{pdfcontactregion} is the contact's state or
+% province; and \moptname{pdfcontacturl} is the contact's \acro{URL} (or
+% multiple, comma-separated \acro{URL}s).
+%
+% \Needspace{2\baselineskip}
+% \moptname{pdfcopyright} defines the copyright text, and
+% \moptname{pdflicenseurl} identifies a \acro{URL} that points to the
+% document's license agreement.
+%
+% \moptname{pdfmetalang} indicates the natural language in which certain
+% metadata---specifically, the document's title, subject, and copyright
+% statement---are written.  The language should be specified using an
+% \acro{IETF} language tag~\cite{IANA2011:lang-tags}, for example,
+% ``|en|'' for English, ``|en-US|'' for specifically United States
+% English, ``|de|'' for German, and so forth.  If \optname{pdfmetalang}
+% is not specified, \pkgname{hyperxmp} assumes the metadata language is
+% the same as the document language (\pkgname{hyperref}'s
+% \moptname{pdflang} option).  If neither \optname{pdfmetalang} nor
+% \optname{pdflang} is specified, \pkgname{hyperxmp} uses only
+% ``|x-default|'' as the metadata language.  Note that ``|x-default|''
+% metadata are always included in addition to the specified metadata
+% language, as the user reading the document may not have specified a
+% language preference.
+%
+% \acro{XMP} can include a universally unique identifier (\acro{UUID})
+% for each document and for each instance of a given document.  By
+% default, \pkgname{hyperxmp} assigns a version~4 (i.e.,~pseudorandom)
+% \acro{UUID}~\cite{Leach2005:uuid} for each of these.  However, a
+% document can alternatively specify a particular document identifier
+% using \moptname{pdfdocumentid} and (not normally recommended) a
+% particular instance identifier using \moptname{pdfinstanceid}.  These
+% should be of the form
+% \texttt{uuid:}\textit{xxxxxxxx}\texttt{-}\textit{xxxx}\texttt{-}\textit{xxxx}\texttt{-}\textit{xxxx}\texttt{-}\textit{xxxxxxxxxxxx},
+% where ``\textit{x}'' is a lowercase hexadecimal number.  For example,
+% \texttt{uuid:53ab7f19-a48c-5177-8bb2-403ad907f632} is a valid argument
+% to \optname{pdfdocumentid} (or \optname{pdfinstanceid}).  See Leach,
+% Mealling, and Salz's \acro{UUID} specification document for details on
+% how to produce the various forms of
+% \acro{UUID}s~\cite{Leach2005:uuid}.  A more freeform mechanism than
+% \optname{pdfinstanceid} for versioning documents is available via
+% \moptname{pdfversionid}.  The version specified by
+% \optname{pdfversionid} can be incremented as~|1|, |2|, |3|,~\dots;
+% identified with a hierarchical numbering scheme (e.g.,~this document
+% is versioned \texttt{\versionnumber} to match the package version); or
+% labeled using any other approach.  One possibility is to use a
+% revision number or commit hash from the version-control software
+% maintaining the document.  For example, the |\gitVer| macro from the
+% \pkgname{gitver} package is an expandable (see
+% Note~\ref{note:expandable} on page~\pageref{note:expandable}) version
+% of the current \href{https://git-scm.com/}{Git} hash that can suitably
+% be passed to \optname{pdfversionid}.
+%
+% Already-published documents can be identified in a number of ways.
+% \moptname{pdfisbn} specifies the \acro{ISBN}.  \moptname{pdfissn}
+% refers to the \acro{ISSN} of the \emph{print} version of the document
+% while \moptname{pdfeissn} refers to the \acro{ISSN} of the
+% \emph{electronic} version of the document.  \moptname{pdfdoi}
+% specifies the \acro{DOI} and should include only the \acro{DOI} name
+% without any \acro{URL} prefix.  For example, specify
+% |pdfdoi={10.1145/3149526.3149532}|, \emph{not}
+% |pdfdoi={https://doi.org/10.1145/3149526.3149532}|.
+% \moptname{pdfurl} points to the complete \acro{URL} for the document.
+% In contrast, \moptname{baseurl} points one level up and is used to
+% resolve relative \acro{URL}s.
+%
+% Already-published documents can further be identified by the
+% publication in which they appear.  \moptname{pdfpublication} specifies
+% the title of the journal, magazine, or other parent document.  The
+% title language is assumed to be the same as the document language
+% (\optname{pdflang}) but can be overridden by preceding the text with a
+% bracketed \acro{ISO} \mbox{639-1} two-letter language code and an
+% optional \acro{ISO} \mbox{3166-1} two-letter region code.  For
+% example, |pdfpublication={[fr]Charlie Hedbo}| indicates a
+% French-language title.  Were the language or pronunciation differences
+% significant, |fr-FR| would indicate specifically the French spoken in
+% France, as opposed to that spoken in, say, Canada (|fr-CA|) or Belgium
+% (|fr-BE|).  The publisher itself can be named using
+% \moptname{pdfpublisher}.
+%
+% \moptname{pdfpubtype} indicates the type of publication in which the
+% document was published.  This should be one of the \acro{PRISM}
+% aggregation types~\cite{PRISM2012:cont-voc} such as |book|, |journal|,
+% |magazine|, |manual|, |report|, or |whitepaper|.  For publications in
+% journals, magazines, and similar periodicals, a document can specify
+% the volume number with \moptname{pdfvolumenum} and the issue number
+% within the volume with \moptname{pdfissuenum}.
+% \moptname{pdfpagerange} indicates the page numbers at which the
+% document appears within the publication.  The intention is that this
+% be a comma-separated list of dash-separated ranges, as in
+% |pdfpagerange={1,4-5}|.  See Note~\ref{note:page-counting} on
+% page~\pageref{note:page-counting} for advice on how to assign
+% \optname{pdfpagerange} semi-automatically.  For books,
+% \moptname{pdfbookedition} names the edition of the book.  This is
+% specified as text, not a number.  As with \optname{pdfpublication}
+% (above), \optname{pdfbookedition} accepts a bracketed language code,
+% as in |pdfbookedition={[en]Second| |edition}|.
+%
+% The number of pages in the published, print version of the document
+% can be expressed with \moptname{pdfnumpages}.
+% Note~\ref{note:page-counting} on page~\pageref{note:page-counting}
+% explains how to automatically assign a value to \optname{pdfnumpages}.
+%
+% \acro{XMP} metadata can include a number of dates (in fact,
+% timestamps, as they include both date and time components).
+% \moptname{pdfdate} specifies the document date.  It is analogous to the
+% \LaTeX\ |\date| command, and, like |\date|, defaults to the date the
+% document was built.  It must be specified in either \acro{XMP}
+% format~\cite{Adobe2012:XMP} or \acro{PDF} format~\cite{Adobe2008:PDF}.
+% \acro{XMP} dates are written in the form
+% \textsc{yyyy}|-|\textsc{mm}|-|\textsc{dd}|T|hh|:|mm|:|ss|+|\textsc{tt}|:|tt.\footnote{Although
+%   allowed by \acro{XMP}, \pkgname{hyperxmp} does not currently accept
+%   fractions of a second in timestamps.}  A W3C
+% recommendation~\cite{Wolf1997:date-time} discusses this format in more
+% detail, but as an example, 14~hours, 15~minutes, 9~seconds past
+% midnight U.S. Mountain Daylight Time (UTC-6) on the 23rd day of
+% September in the year~2014 should be written as
+% \texttt{2014-09-23T14:15:09-06:00}.  This can be truncated (with loss
+% of information) to \texttt{2014-09-23T14:15:09},
+% \texttt{2014-09-23T14:15}, \texttt{2014-09-23}, \texttt{2014-09},
+% or \texttt{2014} but no other subsets.  \acro{PDF} dates are written
+% in the form |D:|\textsc{yyyymmdd}hhmmss|+|\textsc{tt}|'|tt|'|.  The
+% same date in the preceding example would be written as
+% \texttt{D:20140923141509-06'00'} in \acro{PDF} format.
+%
+% The document's creation date, modification date, and metadata date are
+% normally set automatically, but \moptname{pdfcreationdate},
+% \moptname{pdfmoddate}, and \moptname{pdfmetadate} can be used to
+% override the defaults.  Like \optname{pdfdate}, \optname{pdfmetadate}
+% can be specified in either \acro{XMP} or \acro{PDF} format.  However,
+% because \pkgname{hyperref} defines \optname{pdfcreationdate} and
+% \optname{pdfmoddate} and expects these to be written as \acro{PDF}
+% dates, \pkgname{hyperxmp} concomitantly accepts these two dates only
+% in \acro{PDF} format as well.  Note that it's rare that a document
+% would need to specify any of \optname{pdfcreationdate},
+% \optname{pdfmoddate}, or \optname{pdfmetadate}.
+%
+% \moptname{pdftype} describes the type of document being produced.
+% This refers to ``the nature or genre of the
+% resource''~\cite{Adobe2012:XMP} such as |poem|, |novel| or |working|
+% |paper|, as opposed to the file format (always |application/pdf| when
+% generated by \pkgname{hyperxmp}).  Although \optname{pdftype} can be
+% assigned an arbitrary piece of text, the \acro{XMP} specification
+% recommends selecting types from a ``controlled vocabulary'' such as
+% the \acro{DCMI} Type Vocabulary~\cite{DCMI2012:meta-terms}.  The
+% \acro{DCMI} Type Vocabulary currently consists of only |Collection|,
+% |Dataset|, |Event|, |Image|, |InteractiveResource|, |MovingImage|,
+% |PhysicalObject|, |Service|, |Software|, |Sound|, |StillImage|, and
+% |Text|.  \optname{pdftype} defaults to |Text|, which refers to
+% ``books, letters, dissertations, poems, newspapers, articles, archives
+% of mailing lists,''~\cite{DCMI2012:meta-terms} and other forms of
+% text---all things \LaTeX\ is commonly used to typeset.
+%
+% The \moptname{pdfbytes} option expresses the document's file size in
+% bytes.  The intention is for this to be used to display an estimate of
+% download time to a user or to serve as a quick check on whether a file
+% was transmitted correctly between systems.  This feature is easiest to
+% use in conjunction with \pdfTeX's |\pdffilesize| primitive:
+% ``|pdfbytes={\pdffilesize{\jobname.pdf}}|''.  Note that this requires
+% a second run of |pdftex| because it queries the size of the \acro{PDF}
+% file from the \emph{previous} run.
+%
+% A rarely needed option, \moptname{pdfsource}, overrides the name of
+% the \LaTeX\ source file.  It defaults to |\jobname.tex| but can be
+% replaced by any other string.  If \optname{pdfsource} is given an
+% empty argument, no document source will be specified at all.
+%
+% Two other rarely needed options, \moptname{pdfaconformance} and
+% \moptname{pdfapart}, are used in conjunction with \pkgname{hyperref}'s
+% \optname{pdfa} option to claim a particular \acro{PDF/A} standard by
+% which the document abides.  They default to \optname{pdfapart}=|1| and
+% \optname{pdfaconformance}=|B|, indicating the \acro{PDF/A}-\textsc{1b}
+% standard.  These can be changed (with caution) to assert that the
+% document abides by a different standard
+% (e.g.,~\acro{PDF/A}-\textsc{2u}).
+%
+% \bigskip
+%
+% It is usually more convenient to provide values for those options using
+% \pkgname{hyperref}'s |\hypersetup| command than on the |\usepackage|
+% command line.  See
+% \href{http://mirrors.ctan.org/macros/latex/contrib/hyperref/hyperref.pdf}{the
+% \pkgname{hyperref} manual} for more information.
+%
+%
+% \subsection{A complete example}
+%
+% The following is a sample \LaTeX\ document that provides values for
+% most of the metadata options that \pkgname{hyperxmp} recognizes:
+%
+% \Needspace{4\baselineskip}
+% \refstepcounter{pagelabel}
+% \label{page:begin-sample-doc}
+% \begin{verbatim}
+%    \documentclass{article}
+%    \usepackage[utf8]{inputenc}
+%    \usepackage{hyperxmp}
+%    \usepackage[unicode]{hyperref}
+%
+%    \title{%
+%      On a heuristic viewpoint concerning the production and
+%      transformation of light}
+%    \author{Albert Einstein}
+%    \date{March 17, 1905}
+%
+%    \hypersetup{%
+%      pdftitle={%
+%        On a heuristic viewpoint concerning the production and
+%        transformation of light},
+%      pdfsubtitle={[en-US]Putting that bum Maxwell in his place},
+%      pdfauthor={Albert Einstein},
+%      pdfauthortitle={\xmpquote{Technical Assistant\xmpcomma\ Level III}},
+%      pdfdate={1905-03-17},
+%      pdfcopyright={Copyright (C) 1905, Albert Einstein},
+%      pdfsubject={photoelectric effect},
+%      pdfkeywords={energy quanta, Hertz effect, quantum physics},
+%      pdflicenseurl={http://creativecommons.org/licenses/by-nc-nd/3.0/},
+%      pdfcaptionwriter={Scott Pakin},
+%      pdfcontactaddress={Kramgasse 49},
+%      pdfcontactcity={Bern},
+%      pdfcontactpostcode={3011},
+%      pdfcontactcountry={Switzerland},
+%      pdfcontactphone={031 312 00 91},
+%      pdfcontactemail={aeinstein@ipi.ch},
+%      pdfcontacturl={%
+%        http://einstein.biz/,
+%        https://www.facebook.com/AlbertEinstein
+%      },
+%      pdfdocumentid={uuid:6d1ac9ec-4ff2-515a-954b-648eeb4853b0},
+%      pdfversionid={2.998e8},
+%      pdfpublication={[de]Annalen der Physik},
+%      pdfpublisher={Wiley-VCH},
+%      pdfpubtype={journal},
+%      pdfvolumenum={322},
+%      pdfissuenum={6},
+%      pdfpagerange={132-148},
+%      pdfnumpages={17},
+%      pdfissn={0003-3804},
+%      pdfeissn={1521-3889},
+%      pdflang={en},
+%      pdfmetalang={en},
+%      pdfurl={http://www.physik.uni-augsburg.de/annalen/history/einstein-papers/1905_17_132-148.pdf},
+%      pdfdoi={10.1002/andp.19053220607},
+%      pdfbytes={\pdffilesize{\jobname.pdf}}   % Requires pdflatex
+%    }
+%    \XMPLangAlt{de}{pdftitle={Über einen die Erzeugung und Verwandlung des
+%      Lichtes betreffenden heuristischen Gesichtspunkt}}
+%
+%    \begin{document}
+%    \maketitle
+%    A profound formal difference exists between the theoretical
+%    concepts that physicists have formed about gases and other
+%    ponderable bodies, and Maxwell's theory of electromagnetic
+%    processes in so-called empty space\dots
+%    \end{document}
+% \end{verbatim}
+% \refstepcounter{pagelabel}
+% \label{page:end-sample-doc}
+%
+% Compile the document to \acro{PDF} using any of the following
+% approaches:
+%
+% \begin{itemize}
+%   \item \pdfLaTeX
+%   \item \LuaLaTeX
+%   \item \LaTeX~$+$ Dvipdfm
+%   \item \LaTeX~$+$ \Dvips~$+$ Adobe Acrobat Distiller
+%   \item \XeLaTeX
+% \end{itemize}
+%
+% \noindent
+% Unfortunately, the \LaTeX~$+$ \Dvips~$+$ \term{Ghostscript} path
+% doesn't work.
+% \href{http://bugs.ghostscript.com/show_bug.cgi?id=690066}{Ghostscript
+%   bug report~\#690066}, closed with ``\textsc{wontfix}'' status on
+% 2012-05-28, explains that \term{Ghostscript} doesn't honor the
+% \pdfterm{Metadata} tag needed to inject a custom \acro{XMP} packet.
+% Instead, \term{Ghostscript} fabricates an \acro{XMP} packet of its own
+% based on the metadata it finds in the \acro{PDF} file's \pdfterm{Info}
+% dictionary (\pdfterm{Author}, \pdfterm{Title}, \pdfterm{Subject}, and
+% \pdfterm{Keywords}).
+%
+% \bigskip
+%
+% Once the document is compiled, the resulting \acro{PDF} file will
+% contain an \acro{XMP} packet that looks something like that shown in
+% Appendix~\ref{sec:sample-packet}.  Figure~\ref{fig:xmp-metadata-1} is
+% a screenshot of the \acro{XMP} metadata as it appears in Adobe
+% Acrobat's ``Advanced'' metadata dialog box.  Further clicking on the
+% ``Advanced'' item within that dialog box displays all of the
+% document's metadata sorted by schema as shown in
+% Figure~\ref{fig:xmp-metadata-2}.
+%
+% \begin{figure}[htbp]
+%   \includegraphics[width=\linewidth]{einstein1}
+%   \caption{\acro{XMP} metadata as it appears in Adobe Acrobat}
+%   \label{fig:xmp-metadata-1}
+% \end{figure}
+%
+% \begin{figure}[htbp]
+%   \includegraphics[width=\linewidth]{einstein2}
+%   \caption{Additional \acro{XMP} metadata as it appears in Adobe Acrobat}
+%   \label{fig:xmp-metadata-2}
+% \end{figure}
+%
+%
+% \subsection{Usage notes}
+%
+% \usagenote{Conflicting metadata in PDF/A documents}
+% A \acro{PDF} file includes an \pdfterm{Info} dictionary containing
+% \pdfterm{Author}, \pdfterm{Title}, \pdfterm{Subject}, and
+% \pdfterm{Keywords} keys.  The \pkgname{hyperref} package's
+% \optname{pdfauthor}, \optname{pdftitle}, \optname{pdfsubject}, and
+% \optname{pdfkeywords} options assign values to those keys.  The
+% \pkgname{hyperxmp} package additionally uses those options to assign
+% values to various \acro{XMP} metadata: \xmpprop{dc:creator},
+% \xmpprop{dc:title}, \xmpprop{dc:description}, and
+% \xmpprop{pdf:Keywords}.  The \acro{PDF/A} specification indicates that
+% values that appear in both the \acro{PDF} \pdfterm{Info} dictionary
+% and \acro{XMP} packet must match.  The problem is that in \acro{XMP},
+% the author and keywords can be proper lists, as in
+%
+% \Needspace{7\baselineskip}
+% \begin{verbatim}
+%     <dc:creator>
+%       <rdf:Seq>
+%         <rdf:li>Curly Howard</rdf:li>
+%         <rdf:li>Larry Fine</rdf:li>
+%         <rdf:li>Moe Howard</rdf:li>
+%       </rdf:Seq>
+%     </dc:creator>
+% \end{verbatim}
+%
+% \noindent
+% while in \acro{PDF}, the author and keywords are specified as flat
+% strings.  Alas, there is no definition of how a list should be
+% collapsed to a flat string: ``\texttt{Curly Howard, Larry Fine, Moe
+%   Howard}'' or ``\texttt{Curly Howard; Larry Fine; Moe Howard}'' or
+% something else.  I have not yet found a form of flat string that
+% passes all \acro{PDF/A} validators.  Furthermore, when Adobe
+% Acrobat---at least Adobe Acrobat DC (2019) and earlier
+% versions---converts a \acro{PDF} file to \acro{PDF/A} format, it does
+% so by discarding all but the first author, which is an unsatisfying
+% solution.
+%
+% Starting with version~4.0, \pkgname{hyperxmp}'s solution is to
+% suppress writing metadata to the \acro{PDF} \pdfterm{Info} dictionary
+% and write it only to the \acro{XMP} packet.  This appears to pacify
+% \acro{PDF/A} validators yet retains the author and keyword lists in
+% their non-truncated form.  If desired, the \pdfterm{Info} dictionary
+% can be retained by passing the \optname{keeppdfinfo} option to
+% \cs{hypersetup}.
+%
+% \usagenote{Acrobat multiline-field bug}
+% The \acro{IPTC} Photo Metadata schema states that ``the [contact]
+% address is a multiline field''~\cite{IPTC2010:photo-meta}.
+% \pkgname{hyperxmp} converts commas in \optname{pdfcontactaddress}'s
+% argument to line breaks in the generated \acro{XML}\@.  Unfortunately,
+% A bug in Adobe Acrobat---at least in Adobe Acrobat DC (2019) and
+% earlier versions---causes that \acro{PDF} reader to discard line
+% breaks in the contact address.  Interestingly, Adobe Illustrator CS5
+% correctly displays the contact address.  If you find Adobe Acrobat's
+% behavior bothersome, you can redefine the
+% \DescribeMacro{\xmplinesep}|\xmplinesep| macro as a string to use as
+% an address-line separator.  For example, the following replaces all
+% commas appearing in \optname{pdfcontactaddress}'s argument with
+% semicolons:
+%
+% \begin{verbatim}
+%     \renewcommand*{\xmlinesep}{;}
+% \end{verbatim}
+%
+% \usagenote{Object compression}
+% One intention of \acro{XMP} is that metadata embedded in a file be
+% readable even without knowledge of the file's format.  That is, the
+% metadata are expected to appear as plain text.  Although
+% \pkgname{hyperxmp} does its best to honor that intention, it faces
+% a few challenges:
+%
+% \begin{enumerate}
+% \item When run with versions of \LuaLaTeX\ earlier than 0.85,
+%   \pkgname{hyperxmp} leaves all \acro{PDF} objects uncompressed.  This
+%   is due to \LuaLaTeX\ treating object compression as a global
+%   parameter, unlike \pdfLaTeX, which treats it as a local parameter.
+%   Hence, when \pkgname{hyperxmp} requests that the \acro{XMP} packet
+%   be left uncompressed, \LuaLaTeX\ in fact leaves \emph{all}
+%   \acro{PDF} streams uncompressed.  Beginning with version~3.0,
+%   \pkgname{hyperxmp} includes a workaround that correctly leaves only
+%   the \acro{XMP} metadata uncompressed, but this workaround is
+%   implemented only for \LuaLaTeX\ v0.85 onwards.
+%
+% \item \XeLaTeX\ (or, more precisely, the \cmdname{xdvipdfmx} back end)
+%   exhibits the opposite problem.  It compresses \emph{all} \acro{PDF}
+%   objects, including the ones containing \acro{XMP} metadata.  While
+%   Adobe Acrobat can still detect and utilize the \acro{XMP} metadata,
+%   non-\acro{PDF}-aware applications are unlikely to see the metadata.
+%   Three options to consider are to (1)~use a different program
+%   (e.g.,~\LuaLaTeX), (2)~pass the |--output-driver="xdvipdfmx -z0"|
+%   option to \XeLaTeX\ to instruct \cmdname{xdvipdfmx} to turn off all
+%   compression (which will of course make the \acro{PDF} file
+%   substantially larger), or (3)~postprocess the generated \acro{PDF}
+%   file by loading it into the commercial version of Adobe Acrobat and
+%   re-saving it with the Save As\dots\ menu option.
+% \end{enumerate}
+%
+% \usagenote{Literal commas}
+% \pkgname{hyperxmp} splits the \optname{pdfauthor} and
+% \optname{pdfkeywords} lists at commas.  Therefore, when specifying
+% \optname{pdfauthor} and \optname{pdfkeywords}, you should separate
+% items with commas.  Also, omit ``|and|'' and other text that does not
+% belong to any list item.  The following examples should serve as
+% clarification:
+%
+% \begin{description}
+%   \item[Wrong:] |pdfauthor={Jack Napier, Edward Nigma,|
+%     \textcolor{red}{\texttt{and}} |Harvey Dent}|
+%   \item[Wrong:] |pdfauthor={Jack Napier|\textcolor{red}{\texttt{;}}
+%     |Edward Nigma|\textcolor{red}{\texttt{;}}
+%     |Harvey Dent}|
+%   \item[Right:] |pdfauthor={Jack Napier, Edward Nigma, Harvey Dent}|
+% \end{description}
+%
+% \noindent
+% \DescribeMacro{\xmpcomma}
+% \DescribeMacro{\xmpquote}
+% If you need to include a literal comma within an author or keyword
+% list (where commas normally separate list items) or a street address
+% (where commas normally separate lines), use the |\xmpcomma| macro to
+% represent it, and wrap the entire entry containing the comma within
+% |\xmpquote{|\dots|}| as shown below:
+%
+% \begin{verbatim}
+%     pdfauthor={\xmpquote{Jack Napier\xmpcomma\ Jr.},
+%                \xmpquote{Edward Nigma\xmpcomma\ PhD},
+%                \xmpquote{Harvey Dent\xmpcomma\ Esq.}}
+%
+%     pdfcontactaddress={Office of the President,
+%                        \xmpquote{Wayne Enterprises\xmpcomma\ Inc.},
+%                        One Wayne Blvd}
+% \end{verbatim}
+%
+% As of version~2.2 of \pkgname{hyperxmp}, it is acceptable to use
+% |\xmpcomma| and |\xmpquote| within any \pkgname{hyperxmp} option, not
+% just in those in which a comma normally serves as a separator
+% (i.e.,~lists and multiline fields).  Outside of cases in which a comma
+% serves as a separator, |\xmpcomma| is treated as an ordinary comma,
+% and |\xmpquote| returns its argument unmodified.  Hence, it is
+% legitimate to use |\xmpcomma| and |\xmpquote| in cases like the
+% following
+%
+% \begin{verbatim}
+%     pdfauthortitle={\xmpquote{Psychiatrist\xmpcomma\ Arkham Asylum}}
+% \end{verbatim}
+%
+% \noindent
+% (Like most \pkgname{hyperxmp} options, \optname{pdfauthortitle}
+% inserts its argument unmodified in an \acro{XMP} tag.)  When in
+% doubt, use |\xmpcomma| and |\xmpquote|; it should always be safe
+% to do so.
+%
+% \DescribeMacro{\xmptilde}
+% Version~2.4 of \pkgname{hyperxmp} introduces a convenience macro
+% called |\xmptilde|.  |\xmptilde| expands to a literal tilde character
+% instead of the nonbreaking space that ``|~|'' normally represents.
+% Use it to represent \acro{URL}s such as
+% \url{http://www.pakin.org/~scott/} (``|http://www.pakin.org/|\linebreak[0]|\xmptilde|
+% |scott/|'') in options such as \optname{baseurl},
+% \optname{pdfcontacturl} and \optname{pdflicenseurl}.
+%
+% \usagenote{Unicode support}
+% \term{Unicode} support is provided via the \pkgname{hyperref} package.
+% If you specify \optname{unicode}|=true| either as a \pkgname{hyperref}
+% option or as an argument to the |\hypersetup| command, the document
+% can include \term{Unicode} characters in its \acro{XMP} fields.
+%
+% \usagenote{Automatically specified metadata}
+% \optname{pdftitle} defaults to the document's title as specified by
+% |\title{|\dots|}|.  \optname{pdfauthor} defaults to the document's
+% author(s) as specified by |\author{|\dots|}|.  \optname{pdfdate}
+% defaults to the current date and time.  \optname{pdfmetalang}
+% defaults to the same value as \optname{pdflang} if non-empty,
+% ``|x-default|'' otherwise.  An implication of automatic
+% metadata specification is that an author can simply include
+% |\usepackage{hyperxmp}| in a document's preamble and benefit from
+% a modicum of \acro{XMP} metadata with no additional effort.
+%
+% \usagenote{Multilingual metadata}
+% \label{note:multilingual}
+% The \optname{pdfmetalang} option specifies the language in which the
+% document's metadata is written.  It defaults to the value of
+% \optname{pdflang}, which specifies the document language.
+% \DescribeMacro{\XMPLangAlt} As of version~3.3 of \pkgname{hyperxmp},
+% it is possible to include certain metadata---specifically, the
+% document's title, subject, and copyright statement---in more than one
+% language.  The |\XMPLangAlt| macro provides this functionality.  Usage
+% is as follows:
+%
+% \bigskip
+% \indent
+% |\XMPLangAlt| \marg{language} |{| \meta{option}|=|\meta{text},~\dots\ |}|
+% \bigskip
+%
+% \noindent
+% where \meta{language} is an \acro{ISO} \mbox{639-1} two-letter country
+% code with an optional \acro{ISO} \mbox{3166-1} two-letter region code
+% (e.g.,~``|en|'' for English or ``|en-US|'' for specifically US
+% English); \meta{option} is one of ``|pdftitle|'', ``|pdfsubject|'', or
+% ``|pdfcopyright|''; and \meta{text} is the text as expressed in the
+% specified language.  By way, of example, the following code provides
+% the document title in English then specifies an alternative title to
+% use in four other languages:
+%
+% \begin{verbatim}
+%   \hypersetup{%
+%     pdfmetalang={en},
+%     pdftitle={English title}
+%   }
+%   \XMPLangAlt{de}{pdftitle={Deutscher Titel}}
+%   \XMPLangAlt{fr}{pdftitle={Titre fran\c{c}ais}}
+%   \XMPLangAlt{it}{pdftitle={Titolo italiano}}
+%   \XMPLangAlt{rm}{pdftitle={Titel rumantsch}}
+% \end{verbatim}
+%
+% \usagenote{Expandable arguments}
+% \label{note:expandable}
+% All arguments passed to \pkgname{hyperxmp} options must be expandable,
+% in \tex\ terminology.  This implies that any macros that are used in
+% arguments are limited to a relatively small set of operations (such as
+% conditionals and macro expansion) and must produce a string of text.
+% Code (such as macro definitions and arithmetic operations) will be
+% written to \acro{XMP} as code, not as the result of executing the
+% code.
+%
+% By way of example, the macros provided by the \pkgname{texdate}
+% package for typesetting dates are not expandable (at least at the time
+% of this writing).  Hence, the |\printfdate{Y}| in the following code
+% snippet is not replaced by the current year, as one might expect:
+%
+% \begin{verbatim}
+% \usepackage{texdate}
+% \initcurrdate
+% \hypersetup{%
+%   pdfcopyright={Copyright \textcopyright\ \printfdate{Y}, Scott Pakin}
+% }
+% \end{verbatim}
+%
+% \noindent
+% Rather, it generates a \xmpprop{dc:rights} tag of the form
+% ``\texttt{Copyright \textcopyright\ =2=0=by-1by=0\the\year, Scott
+%   Pakin}''.  The garbage in that line corresponds to the remnants of
+% the |\printfdate| code after expanding all of the \tex\ primitives and
+% certain other control sequences it uses to the empty string.  For
+% example, ``|\global\advance\texd@yr| |by-1|'' expands to ``|by-1|''.
+%
+% It is not possible to determine a~priori whether or not a macro is
+% expandable.  The best advice is to carefully inspect the \acro{XMP}
+% package in the output file to ensure that any macros used in arguments
+% to \pkgname{hyperxmp} options produced the expected output.
+%
+% \usagenote{Automatic page counting}
+% \label{note:page-counting}
+% Although \optname{pdfnumpages} and \optname{pdfpagerange} are intended
+% to refer to pages in the final, published version of a document, it
+% would be convenient for them to be generated automatically when
+% producing a standalone \acro{PDF} file that is not intended to be
+% incorporated into a book, journal, or other publication (or if it is
+% known that the pages will not be renumbered for publication).  One
+% approach is to use the \pkgname{totpages} package to keep track of the
+% number of pages.
+%
+% \begin{verbatim}
+%     \hypersetup{%
+%       pdfnumpages={\ref*{TotPages}}
+%     }
+% \end{verbatim}
+%
+% \pkgname{totpages} can likewise help generate \optname{pdfpagerange}.
+% For documents numbered from~1 to~$n$, a simple
+%
+% \begin{verbatim}
+%     \hypersetup{%
+%       pdfpagerange={1-\ref*{TotPages}}
+%     }
+% \end{verbatim}
+%
+% \noindent
+% should suffice.  A bit more effort is needed for documents that change
+% numbering schemes, such as using lowercase Roman numerals for the
+% front matter and Arabic numerals for the main matter and back matter.
+% One approach is to use \cs{label} to mark the first and last page of
+% each numbering scheme and specify \optname{pdfpagerange} as in the
+% following:
+%
+% \Needspace{6\baselineskip}
+% \begin{verbatim}
+%     \hypersetup{%
+%       pdfpagerange={%
+%         \pageref*{page:begin-front}-\pageref*{page:end-front},%
+%         1-\pageref*{TotPages}%
+%       }
+%     }
+% \end{verbatim}
+%
+% I don't know how unnumbered pages (e.g.,~blank pages and the title
+% page) are supposed to be handled.  I suppose blank pages can be
+% omitted from \optname{pdfpagerange}, and title page can be either
+% omitted or listed as |title|, for example.
+%
+% It appears that at least with version~2.00 of \pkgname{totpages}, the
+% |TotPages| label is not defined until after the |\begin{document}|.
+% Consequently, using |TotPages| within a \cs{hypersetup} invocation in
+% the document's preamble will produce ``|??|'' as the page count in the
+% \acro{XMP} packet.  The solution is either to assign
+% \optname{pdfnumpages} and \optname{pdfpagerange} after the
+% |\begin{document}| or to ask \LaTeX\ to do that on your behalf:
+%
+% \begin{verbatim}
+%     \AtBeginDocument{%
+%       \hypersetup{%
+%         pdfnumpages={\ref*{TotPages}},
+%         pdfpagerange={1-\ref*{TotPages}}
+%       }%
+%     }
+% \end{verbatim}
+%
+%
+% \StopEventually{^^A
+% \section{Help Wanted}
+%
+% \paragraph{Comma handling}
+% Ideally, \texttt{\string\xmpquote} should automatically replace all
+% commas with \texttt{\string\xmpcomma}.  Unfortunately, my \tex\ skills
+% are insufficient to pull that off.  If you know a way to make
+% \texttt{\string\xmpquote\string{Hello, world\string}} work with both
+% \term{Unicode} and non-\term{Unicode} encodings and with all
+% \tex\ engines (\pdfTeX, \LuaTeX, \XeTeX, etc.), please send me a code
+% patch.
+%
+% \appendix
+%
+% \section{Sample XMP Packet}
+% \label{sec:sample-packet}
+%
+% The following is an example of a complete \acro{XMP} packet as may be
+% produced by \pkgname{hyperxmp}.  This packet corresponds to the
+% metadata included in the sample \LaTeX\ document presented
+% \vpagerefrange{page:begin-sample-doc}{page:end-sample-doc}.  For
+% clarity, metadata values, either specified explicitly by the document
+% or introduced automatically by \pkgname{hyperxmp}, are colored blue.
+%
+% \input{einstein-xmp}
+%
+% \begin{thebibliography}{1}
+% \bibitem{Adobe2010:pdfmark}
+% Adobe Systems, Inc., San Jose, California.
+% \newblock \emph{{A}dobe {A}crobat~{X} {SDK} Help, pdfmark Reference}.
+% \newblock Available from
+%   \url{http://www.adobe.com/devnet/acrobat/documentation.html}.
+%
+% \bibitem{Adobe1996:postscript}
+% {Adobe Systems, Inc.}
+% \newblock \emph{{P}ost{S}cript Language Reference Manual}.
+% \newblock Addison-Wesley, 2nd edition, January 1996, ISBN: \mbox{0-201-18127-4}.
+%
+% \bibitem{Adobe2008:PDF}
+% Adobe Systems, Inc., San Jose, California.
+% \newblock \emph{Document Management---Portable Document Format---Part 1:
+%   PDF~1.7}, July 2008.
+% \newblock ISO \mbox{32000-1} standard document. Available from
+%   \url{http://wwwimages.adobe.com/www.adobe.com/content/dam/Adobe/en/devnet/pdf/pdfs/PDF32000_2008.pdf}.
+%
+% \bibitem{Adobe2012:XMP}
+% Adobe Systems, Inc., San Jose, California.
+% \newblock \emph{{XMP} Specification Part~1: Data model, Serialization, and Core
+%   Properties}, April 2012.
+% \newblock Available from
+%   \url{http://wwwimages.adobe.com/www.adobe.com/content/dam/Adobe/en/devnet/xmp/pdfs/cc-201306/XMPSpecificationPart1.pdf}.
+%
+% \bibitem{DCMI2012:meta-terms}
+% DCMI Usage Board
+% \newblock \emph{DCMI Metadata Terms}, June~14, 2012.
+% \newblock Available from \url{http://dublincore.org/documents/dcmi-terms/}.
+%
+% \bibitem{Downes1994:ATB15}
+% Michael Downes.
+% \newblock Around the bend~\#15, answers, 4th (last) installment.
+% \newblock \href{news:comp.text.tex}{\texttt{comp.text.tex}} newsgroup posting,
+%   January~3, 1994.
+% \newblock Archived by Google at
+%   \url{http://groups.google.com/group/comp.text.tex/msg/7da7643b9e8f3b48}.
+%
+% \bibitem{PRISM2012:basic-meta}
+% International Digital Enterprise Alliance, Inc.
+% \newblock \emph{Publishing Requirements for Industry Standard Metadata,
+%   Version~3.0: {PRISM} Basic Metadata Specification}, October~12, 2012.
+% \newblock Available from
+%   \url{http://www.prismstandard.org/specifications/3.0/PRISM_Basic_Metadata_3.0.htm}.
+%
+% \bibitem{PRISM2012:cont-voc}
+% International Digital Enterprise Alliance, Inc.
+% \newblock \emph{Publishing Requirements for Industry Standard Metadata,
+%   Version~3.0: {PRISM} Controlled Vocabularies Specification}, October~4, 2012.
+% \newblock Available from
+%   \url{http://www.prismstandard.org/specifications/3.0/PRISM_CV_Spec_3.0.pdf}.
+%
+% \bibitem{IPTC2010:photo-meta}
+% International Press Telecommunications Council.
+% \newblock \emph{{IPTC} Photo Metadata: Core 1.1/Extension 1.1}, July 2010.
+% \newblock Revision~1. Available from
+%   \url{http://www.iptc.org/std/photometadata/specification/IPTC-PhotoMetadata-201007_1.pdf}.
+%
+% \bibitem{IANA2011:lang-tags}
+% {Internet Assigned Numbers Authority}.
+% \newblock Language subtag registry, January~11, 2011.
+% \newblock Available from
+%   \url{http://www.iana.org/assignments/language-subtag-registry}.
+%
+% \bibitem{Leach2005:uuid}
+% Paul~J. Leach, Michael Mealling, and Rich Salz.
+% \newblock A {U}niversally {U}nique {ID}entifier ({UUID}) {URN} namespace.
+% \newblock Request for Comments 4122, Internet Engineering Task Force, Network
+%   Working Group, July 2005.
+% \newblock Category: Standards Track. Available from
+%   \url{http://www.ietf.org/rfc/rfc4122.txt}.
+%
+% \bibitem{PDFA2008:xmp-props}
+% PDF/A Competence Center, Berlin, Germany.
+% \newblock \emph{{T}ech{N}ote~0008: Predefined {XMP} Properties in {PDF/A-1}},
+%   March~20, 2008.
+% \newblock Available from
+%   \url{http://www.pdfa.org/wp-content/uploads/2011/08/tn0008_predefined_xmp_properties_in_pdfa-1_2008-03-20.pdf}.
+%
+% \bibitem{PDFA2008:ext-schemas}
+% PDF/A Competence Center, Berlin, Germany.
+% \newblock \emph{{T}ech{N}ote~0009: {XMP} Extension Schemas in {PDF/A-1}},
+%   March~20, 2008.
+% \newblock Available from
+%   \url{http://www.pdfa.org/wp-content/uploads/2011/08/tn0009_xmp_extension_schemas_in_pdfa-1_2008-03-20.pdf}.
+%
+% \bibitem{Wolf1997:date-time}
+% Misha Wolf and Charles Wicksteed.
+% \newblock Date and time formats.
+% \newblock Note NOTE-datetime, World Wide Web Consortium (W3C), September~15,
+%   1997.
+% \newblock Available from \url{http://www.w3.org/TR/NOTE-datetime}.
+% \end{thebibliography}
+% }
+%
+%
+% \section{Implementation}
+%
+% This section presents the commented \LaTeX\ source code for
+% \pkgname{hyperxmp}.  Read this section only if you want to learn how
+% \pkgname{hyperxmp} is implemented.
+%
+%
+% \subsection{Initial preparation}
+% \label{sec:initial-prep}
+%
+% \changes{v1.2}{2011/04/17}{Made the package compatible with \pkgname{ngerman}.
+%   Thanks to Tobias Mueller for the bug report.}
+%
+% \begin{macro}{\hyxmp@dq@code}
+% The \pkgname{ngerman} package redefines
+% ``\,{\fontencoding{T1}\selectfont\textquotedbl}\,'' as an active
+% character, which causes problems for \pkgname{hyperxmp} when it tries
+% to use that character.  We therefore save the double-quote character's
+% current category code in |\hyxmp@dq@code| and mark the character as
+% category code~12 (``other'').  The original category code is restored
+% at the end of the package code (Section~\ref{sec:clean-up}).
+%    \begin{macrocode}
+\edef\hyxmp@dq@code{\the\catcode`\"}
+\catcode`\"=12
+%    \end{macrocode}
+% \end{macro}
+%
+% \changes{v1.5}{2012/03/10}{Made the \protect\acro{XMP} inclusion more robust.
+%   Thanks to Heiko Oberdiek for the bug report and suggested modifications.}
+%
+% \begin{macro}{\hyxmp@at@end}
+% \begin{macro}{\hyxmp@driver}
+% The |\hyxmp@at@end| macro includes code at the end of the document.
+% For \pdfTeX, the standard |\AtEndDocument| works well enough.  For all
+% the other backends we use |\AtEndDvi| from the \pkgname{atenddvi}
+% package, which is more robust but requires an addition \LaTeX\ run.
+%    \begin{macrocode}
+\def\hyxmp@driver{hpdftex}
+\ifx\hyxmp@driver\Hy@driver
+  \let\hyxmp@at@end=\AtEndDocument
+\else
+  \RequirePackage{atenddvi}
+  \let\hyxmp@at@end=\AtEndDvi
+\fi
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+%
+% \subsection{Integration with \textsf{hyperref}}
+%
+% An important design decision underlying \pkgname{hyperxmp} is that the
+% package should integrate seamlessly with \pkgname{hyperref}.  To that
+% end, \pkgname{hyperxmp} takes its \acro{XMP} metadata from
+% \pkgname{hyperref}'s \optname{baseurl}, \optname{pdfauthor},
+% \optname{pdfkeywords}, \optname{pdflang}, \optname{pdfproducer},
+% \optname{pdfsubject}, and \optname{pdftitle} options.  It also
+% introduces a number of new options, which are listed
+% \vpagerefrange[above]{page:begin-new-options}{page:end-new-options}.
+% For consistency with \pkgname{hyperref}'s document-metadata naming
+% conventions (which are in turn based on \LaTeX's document-metadata
+% naming conventions), we do not prefix metadata-related macro names
+% with our package-specific |\hyxmp@| prefix.  That is, we use names
+% like |\@pdfcopyright| instead of |\hyxmp@pdfcopyright|.
+%
+% \bigskip
+%
+% We load a bunch of helper packages: \pkgname{kvoptions} for
+% package-option processing, \pkgname{pdfescape} and \pkgname{stringenc}
+% for re-encoding \term{Unicode} strings, \pkgname{intcalc} for
+% performing integer calculations (division and modulo),
+% \pkgname{ifxetex} for detecting \XeTeX, and \pkgname{ifmtarg} for
+% testing if a macro argument is empty or all spaces.
+%    \begin{macrocode}
+\RequirePackage{kvoptions}
+\RequirePackage{pdfescape}
+\RequirePackage{stringenc}
+\RequirePackage{intcalc}
+\RequirePackage{ifxetex}
+\RequirePackage{ifmtarg}
+%    \end{macrocode}
+%
+% \begin{macro}{\@ifmtargexp}
+% \begin{macro}{\@ifnotmtargexp}
+% |\@ifmtarg| and |\@ifnotmtarg| do not expand their first argument.
+% Define |\@ifmtargexp| and |\@ifnotmtargexp| as expanding versions of
+% those macros.
+%    \begin{macrocode}
+\def\@ifmtargexp#1{\expandafter\@ifmtarg\expandafter{#1}}
+\def\@ifnotmtargexp#1{\expandafter\@ifnotmtarg\expandafter{#1}}
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\hyxmp@pdfstringdef}
+% \begin{macro}{\hyxmp@textunderscore}
+% Because \pkgname{hyperxmp} uses underscores to represent hard spaces,
+% we need ``|\_|'' to map initially to something other than an
+% underscore, in particular the \acro{ASCII} \acro{NAK}~(|^^U|)
+% character.  To accomplish this, we wrap \pkgname{hyperref}'s
+% |\pdfstringdef| macro with our own version that temporarily does the
+% proper substitution.  Later in the execution, after underscores have
+% been replaced with spaces, we replace \acro{NAK} characters with
+% underscores.
+% \changes{v2.5}{2014/06/19}{Added this macro}
+%    \begin{macrocode}
+\newcommand{\hyxmp@pdfstringdef}[2]{%
+  \let\hyxmp@textunderscore=\textunderscore
+  \let\textunderscore=\hyxmp@uscore
+  \pdfstringdef{#1}{#2}%
+  \let\textunderscore=\hyxmp@textunderscore
+}
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\@pdfdatetime}
+% Prepare to store the document's date and (optionally) time.  Whether
+% specified by the author in \acro{XMP} format or \acro{PDF} format
+% (see Section~\ref{sec:date-manip}) we always store |\@pdfdatetime| as
+% an \acro{XMP}-format string.
+%    \begin{macrocode}
+\def\@pdfdatetime{}
+\define@key{Hyp}{pdfdate}{%
+  \begingroup
+    \Hy@unicodefalse
+%    \end{macrocode}
+% \begin{macro}{\next}
+% Expand \optname{pdfdate}'s argument and convert it to \acro{XMP} format.
+%    \begin{macrocode}
+    \edef\next{%
+      \noexpand\hyxmp@pdfstringdef\noexpand\@pdfdatetime{%
+        \noexpand\hyxmp@as@xmp@date{#1}}%
+    }%
+    \next
+  \endgroup
+}
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\@pdfmetadatetime}
+% Prepare to store the document's metadata date and (optionally) time.
+% Whether specified by the author in \acro{XMP} format or \acro{PDF}
+% format (see Section~\ref{sec:date-manip}) we always store
+% |\@pdfmetadatetime| as an \acro{XMP}-format string.
+%    \begin{macrocode}
+\def\@pdfmetadatetime{}
+\define@key{Hyp}{pdfmetadate}{%
+  \begingroup
+    \Hy@unicodefalse
+%    \end{macrocode}
+% \begin{macro}{\next}
+% Expand \optname{pdfmetadate}'s argument and convert it to \acro{XMP} format.
+%    \begin{macrocode}
+    \edef\next{%
+      \noexpand\hyxmp@pdfstringdef\noexpand\@pdfmetadatetime{%
+        \noexpand\hyxmp@as@xmp@date{#1}}%
+    }%
+    \next
+  \endgroup
+}
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\@pdfcopyright}
+% Prepare to store the document's copyright statement.
+%    \begin{macrocode}
+\def\@pdfcopyright{}
+\define@key{Hyp}{pdfcopyright}{\hyxmp@pdfstringdef\@pdfcopyright{#1}}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@pdftype}
+% Prepare to store the document's logical type, which defaults to ``|Text|''.
+%    \begin{macrocode}
+\def\@pdftype{Text}
+\define@key{Hyp}{pdftype}{\hyxmp@pdfstringdef\@pdftype{#1}}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@pdflicenseurl}
+% Prepare to store the \acro{URL} containing the document's license
+% agreement.
+%    \begin{macrocode}
+\def\@pdflicenseurl{}
+\define@key{Hyp}{pdflicenseurl}{\hyxmp@pdfstringdef\@pdflicenseurl{#1}}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@pdfauthortitle}
+% Prepare to store the author's position/title (e.g.,~Staff Writer).
+%    \begin{macrocode}
+\def\@pdfauthortitle{}
+\define@key{Hyp}{pdfauthortitle}{\hyxmp@pdfstringdef\@pdfauthortitle{#1}}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@pdfcaptionwriter}
+% Prepare to store the name of the person who inserted the
+% \pkgname{hyperxmp} metadata.
+%    \begin{macrocode}
+\def\@pdfcaptionwriter{}
+\define@key{Hyp}{pdfcaptionwriter}{\hyxmp@pdfstringdef\@pdfcaptionwriter{#1}}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@pdfmetalang}
+% Prepare to store the natural language of the document's metadata,
+% typically as an \acro{ISO}~\mbox{639-1} two-letter abbreviation.
+%    \begin{macrocode}
+\def\@pdfmetalang{}
+\define@key{Hyp}{pdfmetalang}{\hyxmp@pdfstringdef\@pdfmetalang{#1}}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@pdfapart}
+% Prepare to store the \acro{PDF/A} part ID, which defaults to~``1''.
+%    \begin{macrocode}
+\def\@pdfapart{1}
+\define@key{Hyp}{pdfapart}{\hyxmp@pdfstringdef\@pdfapart{#1}}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@pdfaconformance}
+% Prepare to store the \acro{PDF/A} conformance ID, which defaults to~``B''.
+%    \begin{macrocode}
+\def\@pdfaconformance{B}
+\define@key{Hyp}{pdfaconformance}{\hyxmp@pdfstringdef\@pdfaconformance{#1}}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@pdfsource}
+% Prepare to store the document's source, which defaults to the value of
+% |\jobname|.
+% \changes{v3.3}{2017/07/16}{Added this macro and the corresponding
+%   \protect\optname{pdfsource} option, at Niklas Beisert's request}
+%    \begin{macrocode}
+\edef\@pdfsource{\jobname.tex}
+\define@key{Hyp}{pdfsource}{\hyxmp@pdfstringdef\@pdfsource{#1}}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\hyxmp@DocumentID}
+% Prepare to store a \acro{UUID} that represents the document.
+% \changes{v3.5}{2018/11/27}{Added the \protect\optname{pdfdocumentid}
+%   option, at Michael Osipov's request}
+%    \begin{macrocode}
+\def\hyxmp@DocumentID{}
+\define@key{Hyp}{pdfdocumentid}{\hyxmp@pdfstringdef\hyxmp@DocumentID{#1}}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\hyxmp@InstanceID}
+% Prepare to store a \acro{UUID} that represents the current instance of
+% the document.
+% \changes{v3.5}{2018/11/27}{Added the \protect\optname{pdfinstanceid}
+%   option, at Michael Osipov's request}
+%    \begin{macrocode}
+\def\hyxmp@InstanceID{}
+\define@key{Hyp}{pdfinstanceid}{\hyxmp@pdfstringdef\hyxmp@InstanceID{#1}}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@pdfversionid}
+% Prepare to store a \acro{UUID} that represents the current version of
+% the document.
+%    \begin{macrocode}
+\def\@pdfversionid{}
+\define@key{Hyp}{pdfversionid}{\hyxmp@pdfstringdef\@pdfversionid{#1}}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@pdfpublication}
+% Prepare to store the name of the publication in which the
+% document was published.
+%    \begin{macrocode}
+\def\@pdfpublication{}
+\define@key{Hyp}{pdfpublication}{\hyxmp@pdfstringdef\@pdfpublication{#1}}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@pdfpubtype}
+% Prepare to store the type of the publication in which the
+% document was published.
+%    \begin{macrocode}
+\def\@pdfpubtype{}
+\define@key{Hyp}{pdfpubtype}{\hyxmp@pdfstringdef\@pdfpubtype{#1}}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@pdfbytes}
+% Prepare to store the size of the file in bytes.
+%    \begin{macrocode}
+\def\@pdfbytes{}
+\define@key{Hyp}{pdfbytes}{\hyxmp@pdfstringdef\@pdfbytes{#1}}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@pdfnumpages}
+% Prepare to store the number of pages in the file.
+%    \begin{macrocode}
+\def\@pdfnumpages{}
+\define@key{Hyp}{pdfnumpages}{\hyxmp@pdfstringdef\@pdfnumpages{#1}}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@pdfissn}
+% Prepare to store the \acro{ISSN} of the publication in which the
+% document was published.
+%    \begin{macrocode}
+\def\@pdfissn{}
+\define@key{Hyp}{pdfissn}{\hyxmp@pdfstringdef\@pdfissn{#1}}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@pdfeissn}
+% Prepare to store the \acro{ISSN} of the electronic version of the
+% publication in which the document was published.
+%    \begin{macrocode}
+\def\@pdfeissn{}
+\define@key{Hyp}{pdfeissn}{\hyxmp@pdfstringdef\@pdfeissn{#1}}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@pdfisbn}
+% Prepare to store the \acro{ISBN} of the publication in which the
+% document was published.
+%    \begin{macrocode}
+\def\@pdfisbn{}
+\define@key{Hyp}{pdfisbn}{\hyxmp@pdfstringdef\@pdfisbn{#1}}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@pdfbookedition}
+% Prepare to store the edition of the book in which the document
+% was published.
+%    \begin{macrocode}
+\def\@pdfbookedition{}
+\define@key{Hyp}{pdfbookedition}{\hyxmp@pdfstringdef\@pdfbookedition{#1}}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@pdfpublisher}
+% Prepare to store the name of the document's publisher.
+%    \begin{macrocode}
+\def\@pdfpublisher{}
+\define@key{Hyp}{pdfpublisher}{\hyxmp@pdfstringdef\@pdfpublisher{#1}}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@pdfvolumenum}
+% Prepare to store the volume identifier of the publication in which the
+% document was published.
+%    \begin{macrocode}
+\def\@pdfvolumenum{}
+\define@key{Hyp}{pdfvolumenum}{\hyxmp@pdfstringdef\@pdfvolumenum{#1}}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@pdfissuenum}
+% Prepare to store the identifier of the issue within a volume of the
+% publication in which the document was published.
+%    \begin{macrocode}
+\def\@pdfissuenum{}
+\define@key{Hyp}{pdfissuenum}{\hyxmp@pdfstringdef\@pdfissuenum{#1}}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@pdfpagerange}
+% Prepare to store the document's range of pages within the publication
+% in which the document was published.
+%    \begin{macrocode}
+\def\@pdfpagerange{}
+\define@key{Hyp}{pdfpagerange}{\hyxmp@pdfstringdef\@pdfpagerange{#1}}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@pdfdoi}
+% Prepare to store a \acro{DOI} that represents the current instance of
+% the document.
+%    \begin{macrocode}
+\def\@pdfdoi{}
+\define@key{Hyp}{pdfdoi}{\hyxmp@pdfstringdef\@pdfdoi{#1}}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@pdfurl}
+% Prepare to store a \acro{URL} that represents where the document
+% can be found.  Note that we do not prepend \optname{baseurl} to
+% the value provided.
+%    \begin{macrocode}
+\def\@pdfurl{}
+\define@key{Hyp}{pdfurl}{\hyxmp@pdfstringdef\@pdfurl{#1}}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@pdfsubtitle}
+% Prepare to store the document's subtitle.
+%    \begin{macrocode}
+\def\@pdfsubtitle{}
+\define@key{Hyp}{pdfsubtitle}{\hyxmp@pdfstringdef\@pdfsubtitle{#1}}
+%    \end{macrocode}
+% \end{macro}
+%
+% The following eight macros---|\@pdfcontactaddress|,
+% |\@pdfcontactcity|, |\@pdfcontactregion|, |\@pdfcontactpostcode|,
+% |\@pdfcontactcountry|, |\@pdfcontactphone|, |\@pdfcontactemail|, and
+% |\@pdfcontacturl|---together specify how to contact the person or
+% institution responsible for the document.
+%
+% \begin{macro}{\@pdfcontactaddress}
+% Prepare to store a street address for the document's contact
+% person\slash institution.  The \acro{IPTC} standard defines this as
+% follows:
+%
+% \begin{quote}
+%   The contact information address part. Comprises an optional company
+%   name and all required information to locate the building or postbox
+%   to which mail should be sent. To that end, the address is a
+%   multiline field.
+% \end{quote}
+%
+% For consistency with the rest of \pkgname{hyperxmp}, we use commas to
+% separate terms, in this case, lines of the address.  The author can
+% use |\xmpquote| and |\xmpcomma| to include literal commas.
+%    \begin{macrocode}
+\def\@pdfcontactaddress{}
+\define@key{Hyp}{pdfcontactaddress}{%
+  \let\xmpcomma=\hyxmp@comma
+  \def\xmpquote##1{##1}%
+  \hyxmp@pdfstringdef\@pdfcontactaddress{#1}%
+  \def\xmpcomma{,}%
+  \let\xmpquote=\relax
+}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@pdfcontactcity}
+% Prepare to store the city of the document's contact person\slash
+% institution.
+%    \begin{macrocode}
+\def\@pdfcontactcity{}
+\define@key{Hyp}{pdfcontactcity}{\hyxmp@pdfstringdef\@pdfcontactcity{#1}}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@pdfcontactregion}
+% Prepare to store the state or province of the document's contact
+% person\slash institution.
+%    \begin{macrocode}
+\def\@pdfcontactregion{}
+\define@key{Hyp}{pdfcontactregion}{\hyxmp@pdfstringdef\@pdfcontactregion{#1}}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@pdfcontactpostcode}
+% Prepare to store the postal code of the document's contact
+% person\slash institution.
+%    \begin{macrocode}
+\def\@pdfcontactpostcode{}
+\define@key{Hyp}{pdfcontactpostcode}{\hyxmp@pdfstringdef\@pdfcontactpostcode{#1}}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@pdfcontactcountry}
+% Prepare to store the country of the document's contact person\slash
+% institution.
+%    \begin{macrocode}
+\def\@pdfcontactcountry{}
+\define@key{Hyp}{pdfcontactcountry}{\hyxmp@pdfstringdef\@pdfcontactcountry{#1}}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@pdfcontactphone}
+% Prepare to store the telephone number of the document's contact
+% person\slash institution.
+%    \begin{macrocode}
+\def\@pdfcontactphone{}
+\define@key{Hyp}{pdfcontactphone}{\hyxmp@pdfstringdef\@pdfcontactphone{#1}}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@pdfcontactemail}
+% Prepare to store the email address of the document's contact
+% person\slash institution.
+%    \begin{macrocode}
+\def\@pdfcontactemail{}
+\define@key{Hyp}{pdfcontactemail}{\hyxmp@pdfstringdef\@pdfcontactemail{#1}}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@pdfcontacturl}
+% Prepare to store the \acro{URL} of the document's contact person\slash
+% institution.
+%    \begin{macrocode}
+\def\@pdfcontacturl{}
+\define@key{Hyp}{pdfcontacturl}{\hyxmp@pdfstringdef\@pdfcontacturl{#1}}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\hyxmp@suppress@pdf@metadata}
+% Suppress \pkgname{hyperref} from writing \pdfterm{Author},
+% \pdfterm{Title}, \pdfterm{Subject}, and other \acro{PDF} metadata into
+% the \pdfterm{Info} dictionary.  This prevents conflicts between the
+% \acro{PDF} metadata and the \acro{XMP} metadata, which cause
+% \acro{PDF/A} validation to fail.  The \acro{PDF} metadata can be
+% restored by passing the \optname{keeppdfinfo} option to
+% |\hypersetup|.
+% \changes{v4.0}{2019/03/31}{Added this macro}
+%    \begin{macrocode}
+\def\hyxmp@suppress@pdf@metadata{%
+  \global\let\PDF@FinishDoc=\@empty
+}
+\define@key{Hyp}{keeppdfinfo}[true]{%
+  \gdef\hyxmp@suppress@pdf@metadata{}%
+}
+%    \end{macrocode}
+% \end{macro}
+%
+% \changes{v2.1}{2012/09/16}{Enabled \protect\pkgname{hyperxmp} and
+%   \protect\pkgname{hyperref} to be loaded in either order.  This addresses
+%   a bug report by Yury Donskoy}
+%
+% We need to capture list arguments (viz.~\optname{pdfauthor} and
+% \optname{pdfkeywords}) before \pkgname{hyperref} converts them to
+% \term{PDFDocEncoding}.  Otherwise, |\xmpcomma| is permanently replaced
+% with a comma, and we lose our ability to change it to a
+% |\hyxmp@comma|.  We therefore need to augment \pkgname{hyperref}'s
+% option processing with our own.  Because \pkgname{hyperref} has not
+% yet been loaded we need to ensure that our augmentation gets loaded in
+% the future: after the |\usepackage{hyperref}| but before options are
+% passed to that package.
+%
+% For lack of a better approach, \pkgname{hyperxmp} redefines
+% |\ProcessKeyvalOptions| to alter the way \pkgname{hyperref} processes
+% \optname{pdfauthor} and \optname{pdfkeywords}.  This is somewhat
+% heavy-handed as it gets executed for \emph{every} subsequently loaded
+% package that uses |\ProcessKeyvalOptions|, but at least it does what
+% we need.  \pkgname{hyperxmp} also redefines |\hypersetup| to do the
+% same thing.  This is required in case \pkgname{hyperref} is loaded
+% before \pkgname{hyperxmp}.
+%
+% \begin{macro}{\hyxmp@pdfauthor}
+% \begin{macro}{\hyxmp@pdfkeywords}
+% Prepare to store the name of the author and a list of keywords.
+%    \begin{macrocode}
+\def\hyxmp@pdfauthor{}
+\def\hyxmp@pdfkeywords{}
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\hyxmp@redefine@Hyp}
+% If not already redefined, redefine \pkgname{hyperref}'s
+% \optname{pdfauthor} and \optname{pdfkeywords} options to properly
+% handle |\xmpcomma| and |\xmpquote|.
+% \changes{v2.1}{2012/09/16}{Added this macro}
+%    \begin{macrocode}
+\newcommand*{\hyxmp@redefine@Hyp}{%
+%    \end{macrocode}
+% \begin{macro}{\hyxmp@Hyp@pdfauthor}
+% Store the old definition of |\KV@Hyp@pdfauthor| in
+% |\hyxmp@Hyp@pdfauthor|, but only if we see that |\KV@Hyp@pdfauthor| is
+% defined and |\hyxmp@Hyp@pdfauthor| isn't.  Otherwise, we'd be defining
+% |\hyxmp@Hyp@pdfauthor| in terms of itself and creating an infinite
+% loop.
+%    \begin{macrocode}
+  \@ifundefined{KV@Hyp@pdfauthor}{}{%
+    \@ifundefined{hyxmp@Hyp@pdfauthor}{%
+      \expandafter\let\expandafter\hyxmp@Hyp@pdfauthor
+        \csname KV@Hyp@pdfauthor\endcsname
+    }{}%
+  }%
+%    \end{macrocode}
+% \begin{macro}{\KV@Hyp@pdfauthor}
+% \begin{macro}{\xmpcomma}
+% \begin{macro}{\xmpquote}
+% \begin{macro}{\hyxmp@and}
+% \begin{macro}{\and}
+% \begin{macro}{\hyxmp@pdfauthor}
+% \begin{macro}{\@pdfauthor}
+% Redefine |\KV@Hyp@pdfauthor| to process its argument twice.  The first
+% time, |\xmpcomma| is defined as a placeholder character
+% (|\hyxmp@comma|) and |\xmpquote| as the identity function.  The result
+% is stored in |\hyxmp@pdfauthor| for use in structured lists (those
+% surrounding each entry with |<rdf:li>|).  The second time, |\xmpcomma|
+% is defined as an ordinary comma, and |\xmpquote| is defined as a macro
+% that puts its argument within double quotes.  The result is stored in
+% |\@pdfauthor| for use in unstructured lists (those in which the entire
+% list appears within a single pair of tags).  In case
+% \optname{pdfauthor} is left unspecified and we copy |\author|'s
+% argument to \optname{pdfauthor}, we temporarily redefine |\and| as the
+% list separator when producing a structured list and as ``|and|'' when
+% producing an unstructured list.
+%    \begin{macrocode}
+  \define@key{Hyp}{pdfauthor}{%
+    \let\xmpcomma=\hyxmp@comma
+    \def\xmpquote####1{####1}%
+    \let\hyxmp@and=\and
+    \def\and{,}%
+    \hyxmp@Hyp@pdfauthor{##1}%
+    \global\let\hyxmp@pdfauthor=\@pdfauthor
+    \def\and{and\space}%
+    \def\xmpcomma{,}%
+    \def\xmpquote####1{"####1"}%
+    \hyxmp@Hyp@pdfauthor{##1}%
+    \def\xmpcomma{,}%
+    \let\xmpquote=\relax
+    \let\and=\hyxmp@and
+  }%
+%    \end{macrocode}
+% \begin{macro}{\hyxmp@Hyp@pdfkeywords}
+% The previous block of code now repeats for the keyword list, starting
+% by storing the old definition of |\KV@Hyp@pdfkeywords| in
+% |\hyxmp@Hyp@pdfkeywords|.
+%    \begin{macrocode}
+  \@ifundefined{KV@Hyp@pdfkeywords}{}{%
+    \@ifundefined{hyxmp@Hyp@pdfkeywords}{%
+      \expandafter\let\expandafter\hyxmp@Hyp@pdfkeywords
+        \csname KV@Hyp@pdfkeywords\endcsname
+    }{}%
+  }%
+%    \end{macrocode}
+% \begin{macro}{\KV@Hyp@pdfkeywords}
+% \begin{macro}{\xmpcomma}
+% \begin{macro}{\xmpquote}
+% \begin{macro}{\hyxmp@pdfkeywords}
+% \begin{macro}{\@pdfkeywords}
+% Redefine |\KV@Hyp@pdfkeywords| to process its argument twice.  The
+% first time, |\xmpcomma| is defined as a placeholder character
+% (|\hyxmp@comma|) and |\xmpquote| as the identity function.  The
+% result is stored in |\hyxmp@pdfkeywords| for use in structured lists
+% (those surrounding each entry with |<rdf:li>|).  The second time,
+% |\xmpcomma| is defined as an ordinary comma, and |\xmpquote| is
+% defined as a macro that puts its argument within double quotes.  The
+% result is stored in |\@pdfkeywords| for use in unstructured lists
+% (those in which the entire list appears within a single pair of tags).
+%    \begin{macrocode}
+  \define@key{Hyp}{pdfkeywords}{%
+    \let\xmpcomma=\hyxmp@comma
+    \def\xmpquote####1{####1}%
+    \hyxmp@Hyp@pdfkeywords{##1}%
+    \global\let\hyxmp@pdfkeywords=\@pdfkeywords
+    \def\xmpcomma{,}%
+    \def\xmpquote####1{"####1"}%
+    \hyxmp@Hyp@pdfkeywords{##1}%
+    \def\xmpcomma{,}%
+    \let\xmpquote=\relax
+  }%
+}
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\hyxmp@ProcessKeyvalOptions}
+% \changes{v2.0}{2012/09/05}{Added this macro}
+% \begin{macro}{\ProcessKeyvalOptions}
+% \changes{v2.0}{2012/09/05}{Added this macro}
+% Redefine \pkgname{kvoptions}'s |\ProcessOptions| command to invoke
+% |\hyxmp@redefine@Hyp| before performing its normal option processing.
+%    \begin{macrocode}
+\let\hyxmp@ProcessKeyvalOptions=\ProcessKeyvalOptions
+\renewcommand*{\ProcessKeyvalOptions}{%
+  \hyxmp@redefine@Hyp
+  \hyxmp@ProcessKeyvalOptions
+}
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\hyxmp@hypersetup}
+% \changes{v2.1}{2012/09/16}{Added this macro}
+% \begin{macro}{\hypersetup}
+% \changes{v2.1}{2012/09/16}{Added this macro}
+% Redefine \pkgname{hyperref}'s |\hypersetup| command to invoke
+% |\hyxmp@redefine@Hyp| before performing its normal option processing.
+%    \begin{macrocode}
+\let\hyxmp@hypersetup=\hypersetup
+\def\hypersetup{%
+  \hyxmp@redefine@Hyp
+  \hyxmp@hypersetup
+}
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\hyxmp@find@metadata}
+% \begin{macro}{\hyxmp@concated@metadata}
+% Issue a warning message if the author failed to specify any metadata
+% at all.  This excludes metadata that is included automatically such as
+% the current timestamp.  Note that we don't consider |\@pdfmetalang| as
+% metadata as that value is meaningful only when used in conjunction
+% with other information.  We also don't examine |\@pdfapart| or
+% |\@pdfaconformance| because those have nonempty default values.
+%    \begin{macrocode}
+\newcommand*{\hyxmp@find@metadata}{%
+  \edef\hyxmp@concated@metadata{%
+    \@baseurl
+    \@pdfauthor
+    \@pdfauthortitle
+    \@pdfbookedition
+    \@pdfbytes
+    \@pdfcaptionwriter
+    \@pdfcontactaddress
+    \@pdfcontactcity
+    \@pdfcontactcountry
+    \@pdfcontactemail
+    \@pdfcontactphone
+    \@pdfcontactpostcode
+    \@pdfcontactregion
+    \@pdfcontacturl
+    \@pdfcopyright
+    \@pdfcreationdate
+    \@pdfdatetime
+    \@pdfdoi
+    \@pdfeissn
+    \@pdfisbn
+    \@pdfissn
+    \@pdfissuenum
+    \@pdfkeywords
+    \@pdflang
+    \@pdflicenseurl
+    \@pdfmetadatetime
+    \@pdfmoddate
+    \@pdfnumpages
+    \@pdfpagerange
+    \@pdfpublication
+    \@pdfpubtype
+    \@pdfsubject
+    \@pdfsubtitle
+    \@pdftitle
+    \@pdftype
+    \@pdfurl
+    \@pdfversionid
+    \@pdfvolumenum
+  }%
+  \ifx\hyxmp@concated@metadata\@empty
+    \PackageWarningNoLine{hyperxmp}{%
+      \jobname.tex did not specify any metadata to\MessageBreak
+      include in the XMP packet.\space\space Please see the\MessageBreak
+      hyperxmp documentation for instructions on how to\MessageBreak
+      provide metadata values to hyperxmp}%
+  \fi
+}
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% Rather than load \pkgname{hyperref} ourself we let the author do it
+% then verify he actually did.  This approach gives the author the
+% flexibility to load \pkgname{hyperxmp} and \pkgname{hyperref} in
+% either order and to call |\hypersetup| anywhere in the document's
+% preamble, not just before \pkgname{hyperxmp} is loaded.
+%    \begin{macrocode}
+\AtBeginDocument{%
+  \@ifpackageloaded{hyperref}{%
+%    \end{macrocode}
+% In older versions of \pkgname{hyperref}, |\@pdflang| is set to
+% |\@empty| if \optname{pdflang} is not specified.  In newer versions of
+% \pkgname{hyperref}, |\@pdflang| is set to |\relax| if
+% \optname{pdflang} is not specified.  The latter is a bit problematic
+% for \pkgname{hyperxmp} because it makes |\@pdflang| non-expandable,
+% which causes a literal ``|\@pdflang|'' to be written as \acro{XMP}
+% metadata.  To avoid that situation we redefine |\@pdflang| as
+% |\@empty| if we see it set to |\relax|.
+% \changes{v2.3a}{2013/04/16}{Bug fix: Redefine \cs{@pdflang} as
+%   \cs{@empty} when \protect\pkgname{hyperref} has set
+%   it to \cs{relax}}
+%    \begin{macrocode}
+    \ifx\@pdflang\relax
+      \let\@pdflang=\@empty
+    \fi
+%    \end{macrocode}
+% If the author explicitly specified the language to use for the
+% document's metadata, we use that.  If not, we use the document
+% language, specified to \pkgname{hyperref} with the \protect\optname{pdflang}
+% option.  If the author did not specify a language, we use |x-default|
+% as the metadata language.
+% \changes{v1.3}{2011/04/25}{Introduced the \protect\optname{pdfmetalang}
+%   package option, which enables an author to specify the language in which he
+%   wrote the document's metadata}
+% \changes{v2.0}{2012/08/02}{New \cs{AtBeginDocument} code from Heiko
+%   Oberdiek to properly encode \cs{@pdfmetalang}}
+% \changes{v3.3}{2017/07/21}{Don't overwrite an existing
+%   \protect\optname{pdfmetalang} with \protect\optname{pdflang} or
+%   \protect\texttt{x-default}.  This addresses a bug report by Niklas
+%   Beisert}
+%    \begin{macrocode}
+    \ifx\@pdfmetalang\@empty
+      \ifx\@pdflang\@empty
+        \let\@pdfmetalang=\hyxmp@x@default
+      \else
+        \edef\@pdfmetalang{\@pdflang}%
+      \fi
+    \fi
+    \hyxmp@xmlify\@pdfmetalang
+%    \end{macrocode}
+% If the author explicitly specified the document date, override the
+% compilation timestamp with the specified date.
+%    \begin{macrocode}
+    \ifx\@pdfdatetime\@empty
+    \else
+      \edef\hyxmp@today{\@pdfdatetime}%
+    \fi
+%    \end{macrocode}
+% If the author left \optname{pdftitle} blank but specified |\title|,
+% use the title for \optname{pdftitle}.  Likewise, if the author left
+% \optname{pdfauthor} blank but specified |\author|, use the author for
+% \optname{pdfauthor}.
+% \changes{v2.7}{2016/02/01}{Automatically use \cs{title} and \cs{author}
+%   if \protect\optname{pdftitle} and \protect\optname{pdfauthor} are left
+%   unspecified.   Thanks to Maciej Radziejewski for the suggestion}
+%    \begin{macrocode}
+    \@ifmtargexp{\@pdftitle}{%
+      \@ifnotmtargexp{\@title}{%
+        \hypersetup{pdftitle={\@title}}%
+      }%
+    }%
+    {}%
+    \@ifmtargexp{\@pdfauthor}{%
+      \@ifnotmtargexp{\@author}{%
+        \hypersetup{pdfauthor={\@author}}%
+      }%
+    }%
+    {}%
+%    \end{macrocode}
+% Older versions of \pkgname{hyperref} write the \pdfterm{Info}
+% dictionary to the \acro{PDF} file at the end of the document.  New
+% versions of \pkgname{hyperref} write the \pdfterm{Info} dictionary to
+% the \acro{PDF} file at the \emph{beginning} of the document.  For
+% compatibility with both old and new \pkgname{hyperref} implementations
+% we suppress writing the \pdfterm{Info} dictionary here, at the
+% beginning of the document.
+% \changes{v4.1}{2019/04/02}{Invoke
+%   \protect\cs{hyxmp@suppress@pdf@metadata} at the beginning of the
+%   document, for compatibility with both newer and older versions of
+%   \protect\pkgname{hyperref}}
+%    \begin{macrocode}
+      \hyxmp@suppress@pdf@metadata
+%    \end{macrocode}
+% We wait until the end of the document to construct the \acro{XMP}
+% packet and write it to the \acro{PDF} document catalog.  This gives
+% the author ample opportunity to provide metadata to \pkgname{hyperref}
+% and thereby \pkgname{hyperxmp}.
+%    \begin{macrocode}
+    \hyxmp@at@end{%
+      \hyxmp@find@metadata
+      \hyxmp@embed@packet
+    }%
+  }{%
+    \PackageWarningNoLine{hyperxmp}{%
+      \jobname.tex failed to include a\MessageBreak
+      \string\usepackage\string{hyperref\string}
+      in the preamble.\MessageBreak
+      Consequently, all hyperxmp functionality will be\MessageBreak
+      disabled}%
+  }%
+}
+%    \end{macrocode}
+%
+%
+% \subsection{Manipulating author-supplied data}
+%
+% The author provides metadata information to \pkgname{hyperxmp} via
+% package options to \pkgname{hyperref} or via \pkgname{hyperref}'s
+% |\hypersetup| command.  The functions in this section convert
+% author-supplied lists (e.g.,~|pdfkeywords={foo, bar, baz}|) into
+% \LaTeX\ lists (e.g.,~|\@elt {foo}| |\@elt {bar}| |\@elt {baz}|) that
+% can be more easily manipulated (Section~\ref{sec:list-manip}); trim
+% spaces off the ends of strings (Section~\ref{sec:trim-spaces}); and,
+% in Section~\ref{sec:text-xml}, convert text to \acro{XML} (e.g.,~from
+% |<scott+hyxmp@pakin.org>| to |&lt;scott+hyxmp@pakin.org&gt;|).
+%
+% \subsubsection{List manipulation}
+% \label{sec:list-manip}
+%
+% We define a macro for converting a list of comma-separated elements
+% (e.g.,~the list of \acro{PDF} keywords) to a list of \LaTeX\
+% |\@elt|-separated elements.
+%
+% \begin{macro}{\hyxmp@commas@to@list}
+% Given a macro name~(|#1|) and a comma-separated list~(|#2|), define
+% the macro name as the elements of the list, each preceded by |\@elt|.
+% (Executing the macro therefore applies |\@elt| to each element in
+% turn.)
+%    \begin{macrocode}
+\newcommand*{\hyxmp@commas@to@list}[2]{%
+  \gdef#1{}%
+  \expandafter\hyxmp@commas@to@list@i\expandafter#1#2,,%
+}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\hyxmp@commas@to@list@i}
+% \begin{macro}{\next}
+% Recursively construct macro~|#1| from comma-separated list~|#2|.  Stop
+% if |#2| is empty.
+%    \begin{macrocode}
+\def\hyxmp@commas@to@list@i#1#2,{%
+  \gdef\hyxmp@sublist{#2}%
+  \ifx\hyxmp@sublist\@empty
+    \let\next=\relax
+  \else
+    \hyxmp@trimspaces\hyxmp@sublist
+    \@cons{#1}{{\hyxmp@sublist}}%
+    \def\next{\hyxmp@commas@to@list@i{#1}}%
+  \fi
+  \next
+}
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\xmpcomma}
+% Because \pkgname{hyperxmp} splits lists at commas, a comma cannot
+% normally be used within a list.  We there provide an |\xmpcomma| macro
+% that can expand to either a true comma or a placeholder character
+% depending on the situation.  Here, we bind it to a comma so it can be
+% used in \emph{any} \pkgname{hyperxmp} option, not just those that treat
+% commas specially.
+% \changes{v2.0}{2012/08/25}{Added this macro}
+% \changes{v2.2}{2012/12/07}{Changed the default from
+%   \texttt{\string\string\string\relax} to an ordinary comma}
+%    \begin{macrocode}
+\def\xmpcomma{,}%
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\hyxmp@comma}
+% This is what |\xmpcomma| maps to during list construction.  We assume
+% that documents will never otherwise use an \acro{ETX} (|^^C|)
+% character in their \acro{XMP} metadata.
+% \changes{v2.0}{2012/08/25}{Added this macro}
+%    \begin{macrocode}
+\bgroup
+  \catcode`\^^C=11
+  \gdef\hyxmp@comma{^^C}
+\egroup
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\hyxmp@uscore}
+% This is what |\_| temporarily maps to during packet construction.
+% Because underscores are replaced by spaces, we need a mechanism to
+% preserve user-specified underscores (e.g.,~in email addresses).  We
+% assume that documents will never otherwise use an \acro{NAK} (|^^U|)
+% character in their \acro{XMP} metadata.
+% \changes{v2.5}{2014/06/19}{Added this macro}
+%    \begin{macrocode}
+\bgroup
+  \catcode`\^^U=11
+  \gdef\hyxmp@uscore{^^U}
+\egroup
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\xmpquote}
+% Adobe Acrobat likes to see double quotes around list elements that
+% contain commas when the entire list appears within a single \acro{XMP}
+% tag (e.g.,~|<pdf:Keywords>|).  However, it doesn't like to see double
+% quotes around list elements that contain commas when the list is
+% broken up into individual components (i.e.,~using |<rdf:li>| tags).
+% We therefore introduce an |\xmpquote| macro that quotes or doesn't
+% quote its argument based on context.  Here, we bind |\xmpquote| to
+% |\relax| to prevent it from prematurely quoting or not quoting.
+% \changes{v2.0}{2012/09/10}{Added this macro}
+%    \begin{macrocode}
+\let\xmpquote=\relax
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\xmptilde}
+% As a convenience for the user, we define |\xmptilde| as a category~12
+% (other) ``|~|'' character.
+% \changes{v2.4}{2014/01/01}{Added this macro}
+%    \begin{macrocode}
+\bgroup
+  \catcode`\~=12%
+  \gdef\xmptilde{~}%
+\egroup
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\XMPTruncateList}
+% \changes{v2.0}{2012/09/07}{Added this macro}
+% \changes{v2.3b}{2013/07/18}{Made all definitions local to avoid
+%   spurious \texttt{Too many unprocessed floats} errors when running
+%   with \string\pkgname{memoir}}
+% \changes{v4.0}{2019/03/31}{Deprecated this macro}
+% \begin{macro}{\hyxmp@temp@str}
+% \begin{macro}{\hyxmp@temp@list}
+% \begin{macro}{\@elt}
+% As a workaround for the inability of older Adobe Acrobat versions to
+% display author lists correctly we introduce a hack that replaces a
+% list with its first element.  One can then write
+% ``|\XMPTruncateList{pdfauthor}|'' and have Adobe Acrobat display the
+% author list correctly.
+%    \begin{macrocode}
+\newcommand{\XMPTruncateList}[1]{{%
+    \PackageWarning{hyperxmp}{%
+      \noexpand\XMPTruncateList has been deprecated since\MessageBreak
+      hyperxmp 4.0 and may be removed in future\MessageBreak
+      versions of the package.  \noexpand\XMPTruncateList\MessageBreak
+      was found}%
+  \edef\hyxmp@temp@str{\csname hyxmp@#1\endcsname}%
+  \hyxmp@commas@to@list{\hyxmp@temp@list}{\hyxmp@temp@str}%
+  \def\@elt##1{%
+    \expandafter\gdef\csname @#1\endcsname{##1}%
+    \let\@elt=\@gobble
+  }
+  \hyxmp@temp@list
+}}
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+%
+% \subsubsection{Date manipulation}
+% \label{sec:date-manip}
+%
+% \pkgname{hyperxmp} needs to manipulate two types of date (really,
+% timestamp) formats: \acro{PDF} format and \acro{XMP} format.
+% \acro{PDF} timestamps are of the form
+% ``|D:|\textsc{yyyymmdd}hhmmss|+|\textsc{tt}|'|tt|'|''
+% \makeatletter
+% \@ifundefined{pdffeedback}{^^A
+%   \@ifundefined{pdfcreationdate}{^^A
+%   }{^^A
+%     (e.g.,~\texttt{\pdfcreationdate})^^A
+%   }^^A
+% }{^^A
+%   (e.g.,~\texttt{\pdffeedback creationdate})^^A
+% }
+% \makeatother
+% ~\cite{Adobe2008:PDF}, while \acro{XMP} timestamps are of the form
+% ``\textsc{yyyy}|-|\textsc{mm}|-|\textsc{dd}|T|hh|:|mm|:|ss|+|\textsc{tt}|:|tt''
+% \makeatletter
+% \@ifundefined{pdffeedback}{^^A
+%   \@ifundefined{pdfcreationdate}{^^A
+%     \unskip
+%   }{^^A
+%     (e.g.,~\texttt{\expandafter\hyxmp@pdf@to@xmp@date\pdfcreationdate})^^A
+%   }^^A
+% }{^^A
+%   (e.g.,~\texttt{\expandafter\hyxmp@pdf@to@xmp@date\pdffeedback creationdate})^^A
+% }^^A
+% \makeatother
+% ~\cite{Adobe2012:XMP}.  The |\hyxmp@as@pdf@date| and
+% |\hyxmp@as@xmp@date| macros defined in this section facilitate
+% timestamp conversions to \acro{PDF} and \acro{XMP} formats,
+% respectively.
+%
+% \begin{macro}{\hyxmp@first@char}
+% \begin{macro}{\hyxmp@first@char@i}
+% Return the first character of a string.  This macro is fully expandable.
+%    \begin{macrocode}
+\def\hyxmp@first@char#1{\hyxmp@first@char@i#1\relax}
+\def\hyxmp@first@char@i#1#2\relax{#1}
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\hyxmp@as@xmp@date}
+% If necessary, convert a timestamp to \acro{XMP} format.  That is, if
+% the timestamp is in \acro{PDF} format, convert it; otherwise, leave it
+% unmodified.  This macro is fully expandable.
+% \changes{v3.2}{2017/02/20}{Added this macro}
+%    \begin{macrocode}
+\def\hyxmp@as@xmp@date#1{%
+  \expandafter\ifx\hyxmp@first@char@i#1\relax D%
+    \hyxmp@pdf@to@xmp@date{#1}%
+  \else
+    #1%
+  \fi
+}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\hyxmp@pdf@to@xmp@date}
+% Convert a timestamp from \acro{PDF} format to \acro{XMP} format.  This
+% macro is fully expandable.
+% \changes{v2.4}{2013/12/24}{Added this macro}
+%    \begin{macrocode}
+\def\hyxmp@pdf@to@xmp@date#1:#2#3#4#5#6#7#8#9{%
+  #2#3#4#5-#6#7-#8#9%
+  \hyxmp@parse@time
+}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\hyxmp@parse@time}
+% This is a helper function for |\hyxmp@pdf@to@xmp@date|.
+% |\hyxmp@pdf@to@xmp@date| proper parses only the year, month, and day
+% then calls |\hyxmp@parse@time|.  |\hyxmp@parse@time| parses the
+% hours, minutes, and seconds then calls |\hyxmp@parse@tz@char|.
+% \changes{v2.4}{2013/12/24}{Added this macro}
+%    \begin{macrocode}
+\def\hyxmp@parse@time#1#2#3#4#5#6{%
+  T#1#2:#3#4:#5#6%
+  \hyxmp@parse@tz@char
+}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\hyxmp@parse@tz@char}
+% This is another helper function for |\hyxmp@pdf@to@xmp@date|.  So far,
+% the date and time have been parsed.  |\hyxmp@parse@tz@char| parses the
+% first character of the timezone descriptor.  This can be one of
+% ``|+|'' for eastern timezones (\mbox{UTC$+x$}, including Asia,
+% Oceania, and most of Europe), ``|-|'' for western timezones
+% (\mbox{UTC$-x$}, primarily the Americas), or ``|Z|'' for Zulu time
+% (\mbox{UTC$+0$}).  Timezones beginning with ``|+|'' or ``|-|'' are
+% followed by an offset in hours and minutes (parsed by
+% |\hyxmp@parse@tz|; timezones beginning with ``|Z|'' are not.
+% \changes{v2.4}{2013/12/24}{Added this macro}
+%    \begin{macrocode}
+\def\hyxmp@parse@tz@char#1{%
+  #1%
+  \ifx#1-%
+    \expandafter\hyxmp@parse@tz
+  \else
+    \ifx#1+%
+      \expandafter\hyxmp@parse@tz
+    \fi
+  \fi
+}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\hyxmp@parse@tz}
+% This is the final helper function for |\hyxmp@pdf@to@xmp@date|.  It
+% parses the piece of the timezone comprising the offset from
+% Coordinated Universal Time, measured in hours and minutes.
+% \changes{v2.4}{2013/12/24}{Added this macro}
+%    \begin{macrocode}
+\def\hyxmp@parse@tz#1'#2'{%
+  #1:#2%
+}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\hyxmp@as@pdf@date}
+% If necessary, convert a timestamp to \acro{PDF} format.  That is, if
+% the timestamp is in \acro{XMP} format, convert it; otherwise, leave it
+% unmodified.  This macro is fully expandable.
+% \changes{v3.2}{2017/02/20}{Added this macro}
+%    \begin{macrocode}
+\def\hyxmp@as@pdf@date#1{%
+  \expandafter\ifx\hyxmp@first@char@i#1\relax D%
+    #1%
+  \else
+    \hyxmp@xmp@to@pdf@date{#1}%
+  \fi
+}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\hyxmp@xmp@to@pdf@date}
+% Convert a timestamp from \acro{XMP} format to \acro{PDF} format.  This
+% macro is fully expandable.
+% \changes{v2.4}{2013/12/24}{Added this macro}
+%    \begin{macrocode}
+\def\hyxmp@xmp@to@pdf@date#1{%
+  D:\hyxmp@xmp@to@pdf@date@i#1\relax\relax
+}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\hyxmp@xmp@to@pdf@date@i}
+% Parse the year for |\hyxmp@xmp@to@pdf@date|.
+%    \begin{macrocode}
+\def\hyxmp@xmp@to@pdf@date@i#1#2#3#4#5#6{%
+  #1#2#3#4%
+  \ifx#5-%
+    \expandafter\hyxmp@xmp@to@pdf@date@ii\expandafter#6%
+  \fi
+}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\hyxmp@xmp@to@pdf@date@ii}
+% Parse the month for |\hyxmp@xmp@to@pdf@date|.
+%    \begin{macrocode}
+\def\hyxmp@xmp@to@pdf@date@ii#1#2#3#4{%
+  #1#2%
+  \ifx#3-%
+    \expandafter\hyxmp@xmp@to@pdf@date@iii\expandafter#4%
+  \fi
+}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\hyxmp@xmp@to@pdf@date@iii}
+% Parse the day for |\hyxmp@xmp@to@pdf@date|.
+%    \begin{macrocode}
+\def\hyxmp@xmp@to@pdf@date@iii#1#2#3#4{%
+  #1#2%
+  \ifx#3T%
+    \expandafter\hyxmp@xmp@to@pdf@date@iv\expandafter#4%
+  \fi
+}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\hyxmp@xmp@to@pdf@date@iv}
+% Parse the hour for |\hyxmp@xmp@to@pdf@date|.
+%    \begin{macrocode}
+\def\hyxmp@xmp@to@pdf@date@iv#1#2#3#4{%
+  #1#2%
+  \ifx#3:%
+    \expandafter\hyxmp@xmp@to@pdf@date@v\expandafter#4%
+  \fi
+}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\hyxmp@xmp@to@pdf@date@v}
+% Parse the minute for |\hyxmp@xmp@to@pdf@date|.
+%    \begin{macrocode}
+\def\hyxmp@xmp@to@pdf@date@v#1#2#3#4{%
+  #1#2%
+  \ifx#3:%
+    \expandafter\hyxmp@xmp@to@pdf@date@vi\expandafter#4%
+  \fi
+}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\hyxmp@gobbletwo}
+% This is exactly the same as \LaTeXe's |\@gobbletwo| but needs to be a
+% different literal for |\hyxmp@xmp@to@pdf@date@vii|'s pattern-matching
+% to work.
+%    \begin{macrocode}
+\let\hyxmp@gobbletwo=\@gobbletwo
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\hyxmp@xmp@to@pdf@date@vi}
+% Parse the second for |\hyxmp@xmp@to@pdf@date|.  The challenge here is
+% that we need to handle four cases for the character following the
+% seconds---``|+|'', ``|-|'', ``|Z|'', and no character---without sacrificing
+% expandability.  Our tricky solution is to insert a |\@gobbletwo| as a
+% sentinel and let |\hyxmp@xmp@to@pdf@date@vi| discard everything up to
+% that sentinel (i.e.,~all the other conditionals).
+%    \begin{macrocode}
+\def\hyxmp@xmp@to@pdf@date@vi#1#2#3#4{%
+  #1#2%
+  \ifx#3+%
+    +\expandafter\hyxmp@xmp@to@pdf@date@vii
+  \fi
+  \ifx#3-%
+    -\expandafter\hyxmp@xmp@to@pdf@date@vii
+  \fi
+  \ifx#3Z%
+    Z%
+  \fi
+  \ifx#3\relax
+    \expandafter\hyxmp@gobbletwo
+  \fi
+  \@gobbletwo #4%
+}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\hyxmp@xmp@to@pdf@date@vii}
+% Parse the time-zone hours for |\hyxmp@xmp@to@pdf@date|.
+%    \begin{macrocode}
+\def\hyxmp@xmp@to@pdf@date@vii#1\@gobbletwo#2#3#4#5{%
+  #2#3%
+  \ifx#4:%
+    \expandafter\hyxmp@xmp@to@pdf@date@viii\expandafter#5%
+  \fi
+}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\hyxmp@xmp@to@pdf@date@viii}
+% Parse the time-zone minutes for |\hyxmp@xmp@to@pdf@date|.
+%    \begin{macrocode}
+\def\hyxmp@xmp@to@pdf@date@viii#1#2#3#4{%
+  '#1#2'%
+}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\hyxmp@today@define}
+% Use \tex\ primitives to define a given macro as today's date in
+% \textsc{yyyy}-\textsc{mm}-\textsc{dd}|T|hh|:|mm format.
+% \changes{v2.4}{2013/12/21}{Added this macro}
+% \changes{v3.0}{2016/07/03}{Modified to accept the name of a macro
+%   to define}
+% \changes{v3.2}{2017/02/21}{Modified to include hours and minutes}
+%    \begin{macrocode}
+\def\hyxmp@today@define#1{%
+%    \end{macrocode}
+% The date is a straightforward representation of \tex's |\year|,
+% |\month|, and |\day| primitives, with the latter two zero-padded to
+% two digits apiece.
+%    \begin{macrocode}
+  \xdef#1{\the\year}%
+  \ifnum\month<10
+    \xdef#1{#1-0\the\month}%
+  \else
+    \xdef#1{#1-\the\month}%
+  \fi
+  \ifnum\day<10
+    \xdef#1{#1-0\the\day}%
+  \else
+    \xdef#1{#1-\the\day}%
+  \fi
+%    \end{macrocode}
+% \tex\ does not provide the time in terms of separate hours and minutes
+% but rather as the total number of minutes since midnight (|\time|).
+% There's no mechanism in \tex\ to query the number of seconds since
+% midnight or the timezone so we omit those fields when defining
+% macro~|#1|.
+%    \begin{macrocode}
+  \@tempcnta=\time
+  \divide\@tempcnta by 60%
+  \ifnum\@tempcnta<10%
+    \xdef#1{#1T0\the\@tempcnta}%
+  \else
+    \xdef#1{#1T\the\@tempcnta}%
+  \fi
+  \multiply\@tempcnta by -60%
+  \advance\@tempcnta by \time
+  \ifnum\@tempcnta<10%
+    \xdef#1{#1:0\the\@tempcnta}%
+  \else
+    \xdef#1{#1:\the\@tempcnta}%
+  \fi
+}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\hyxmp@today}
+% Define |\hyxmp@today| as the current date and (if available) time and
+% timezone in \acro{XMP} \xmpterm{Date} format~\cite{Adobe2012:XMP}.
+% \changes{v2.4}{2013/12/24}{Modified the code to parse the time and
+%   timezone from \texttt{\string\string\string\pdfcreationdate}, as
+%   proposed by Florian Breitwieser}
+%    \begin{macrocode}
+\@ifundefined{pdffeedback}{%
+  \@ifundefined{pdfcreationdate}{%
+%    \end{macrocode}
+% Case 1: Neither |\pdffeedback| nor |\pdfcreationdate| is defined
+% (\XeLaTeX\ and regular \LaTeX).
+%    \begin{macrocode}
+    \hyxmp@today@define\hyxmp@today
+  }{%
+%    \end{macrocode}
+% Case 2: |\pdfcreationdate| is defined (\pdfLaTeX\ and pre-0.85 \LuaLaTeX).
+%    \begin{macrocode}
+    \edef\hyxmp@today{\expandafter\hyxmp@pdf@to@xmp@date\pdfcreationdate}%
+  }%
+}{%
+%    \end{macrocode}
+% Case 3: |\pdffeedback| is defined (\LuaLaTeX~0.85+).
+%    \begin{macrocode}
+  \edef\hyxmp@today{\expandafter\hyxmp@pdf@to@xmp@date\pdffeedback creationdate}%
+}
+%    \end{macrocode}
+% \end{macro}
+%
+%
+% \subsubsection{Trimming leading and trailing spaces}
+% \label{sec:trim-spaces}
+%
+% To make it easier for \acro{XMP} processors to manipulate our output we
+% define a |\hyxmp@trimspaces| macro to strip leading and trailing
+% spaces from various data fields.
+%
+% \begin{macro}{\hyxmp@trimspaces}
+% Redefine a macro as its previous value but without leading or trailing
+% spaces.  This code---as well as that for its helper macros,
+% |\hyxmp@trimb| and |\hyxmp@trimc|---was taken almost verbatim from a
+% solution to an \emph{Around the Bend} puzzle~\cite{Downes1994:ATB15}.
+% Inline comments are also taken from the solution text.
+%    \begin{macrocode}
+\catcode`\Q=3
+%    \end{macrocode}
+% |\hyxmp@trimspaces\x| redefines |\x| to have the same replacement text
+% sans leading and trailing space tokens.
+%    \begin{macrocode}
+\newcommand{\hyxmp@trimspaces}[1]{%
+%    \end{macrocode}
+% Use grouping to emulate a multi-token |afterassignment| queue.
+%    \begin{macrocode}
+  \begingroup
+%    \end{macrocode}
+% Put ``|\toks 0 {|'' into the |afterassignment| queue.
+%    \begin{macrocode}
+  \aftergroup\toks\aftergroup0\aftergroup{%
+%    \end{macrocode}
+% Apply |\hyxmp@trimb| to the replacement text of |#1|, adding a leading
+% |\noexpand| to prevent brace stripping and to serve another purpose
+% later.
+%    \begin{macrocode}
+  \expandafter\hyxmp@trimb\expandafter\noexpand#1Q Q}%
+%    \end{macrocode}
+% Transfer the trimmed text back into |#1|.
+%    \begin{macrocode}
+  \edef#1{\the\toks0}%
+}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\hyxmp@trimb}
+% |\hyxmp@trimb| removes a trailing space if present, then calls
+% |\hyxmp@trimc| to clean up any leftover bizarre |Q|s, and trim a
+% leading space. In order for |\hyxmp@trimc| to work properly we need to
+% put back a |Q| first.
+%    \begin{macrocode}
+\def\hyxmp@trimb#1 Q{\hyxmp@trimc#1Q}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\hyxmp@trimc}
+% Execute |\vfuzz| assignment to remove leading space; the |\noexpand|
+% will now prevent unwanted expansion of a macro or other expandable
+% token at the beginning of the trimmed text.  The |\endgroup| will feed
+% in the |\aftergroup| tokens after the |\vfuzz| assignment is
+% completed.
+%    \begin{macrocode}
+\def\hyxmp@trimc#1Q#2{\afterassignment\endgroup \vfuzz\the\vfuzz#1}
+\catcode`\Q=11
+%    \end{macrocode}
+% \end{macro}
+%
+%
+% \subsubsection{Converting text to XML}
+% \label{sec:text-xml}
+%
+% The ``|<|'', ``|>|'', and ``|&|'' characters are significant to \acro{XML}.
+% We therefore need to escape them in any author-supplied text.
+%
+% \begin{macro}{\ifhyxmp@unicodetex}
+% \changes{v2.0}{2012/08/02}{Added by Heiko Oberdiek}
+% \begin{macro}{\hyxmp@unicodetextrue}
+% \begin{macro}{\hyxmp@unicodetexfalse}
+% \XeTeX\ and \LuaTeX\ natively support \term{Unicode}.  We define the
+% conditional |\ifhyxmp@unicodetex| to check for these so we can
+% properly handle encoding conversions.  The trick here is that
+% \term{Unicode} \tex\ implementations compare decimal~64 to
+% hexadecimal~40 (decimal~64), specified with four carets, and take the
+% \textsc{true} branch; non-\term{Unicode} \tex\ implementations compare
+% decimal~64 to character~``|^|'' (decimal~94), ignore the ``|^^0040|''
+% and the rest of the \textsc{true} branch, and take the \textsc{false}
+% branch.
+%   \begin{macrocode}
+\newif\ifhyxmp@unicodetex
+\ifnum64=`\^^^^0040\relax
+  \hyxmp@unicodetextrue
+\else
+  \hyxmp@unicodetexfalse
+\fi
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\hyxmp@reencode}
+% This is now a placeholder macro needed only for |\@pdfmetalang| in
+% the |\begin{document}|.
+% \changes{v1.3}{2011/04/25}{Introduced this macro to re-encode Unicode
+%   strings as 8-bit strings before manipulating them into \acro{XMP}
+%   schema.  This change addresses a bug reported by Martin M\"unch}
+% \changes{v2.0}{2012/08/02}{Replaced with an empty macro by Heiko Oberdiek}
+%    \begin{macrocode}
+\newcommand*{\hyxmp@reencode}[1]{}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\SE->pdfdoc@03}
+% Preserve \acro{ETX} (|^^C|), which is normally an invalid character in
+% \term{PDFDocEncoding}.  We use it in \pkgname{hyperxmp} (and
+% specifically in |\hyxmp@xmlify| below) as a list-element separator.
+%    \begin{macrocode}
+\expandafter\def\csname SE->pdfdoc@03\endcsname{0003}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\SE->pdfdoc@15}
+% Preserve \acro{NAK} (|^^U|), which is normally an invalid character in
+% \term{PDFDocEncoding}.  We use it in \pkgname{hyperxmp} (and
+% specifically in |\hyxmp@xmlify| below) as a placeholder for an
+% underscore character.
+%    \begin{macrocode}
+\expandafter\def\csname SE->pdfdoc@15\endcsname{0015}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\hyxmp@xmlify}
+% \changes{v2.0}{2012/08/02}{Completely rewritten by Heiko Oberdiek to
+%   better support Unicode-enabled \TeX\ programs}
+% \begin{macro}{\hyxmp@xmlified}
+% \begin{macro}{\hyxmp@text}
+% Given a piece of text defined using |\pdfstringdef| (i.e.,~with many
+% special characters redefined to have category code~11), set
+% |\hyxmp@xmlified| to the same text but with all occurrences of~``|<|''
+% replaced with~|&lt;|, all occurrences of~``|>|'' replaced with~|&gt;|,
+% and all occurrences of~``|&|'' replaced with~|&amp;|.
+%    \begin{macrocode}
+\newcommand*{\hyxmp@xmlify}[1]{%
+  \gdef\hyxmp@xmlified{}%
+%    \end{macrocode}
+% Escaped \acro{PDF} string~$\rightarrow$ \term{PDFDocEncoding}/\term{Unicode}
+%    \begin{macrocode}
+  \EdefUnescapeString\hyxmp@text{#1}%
+  \ifhyxmp@unicodetex
+%    \end{macrocode}
+% \term{PDFDocEncoding}/\term{Unicode}~$\rightarrow$ \acro{UTF-32BE}
+%    \begin{macrocode}
+    \hyxmp@is@unicode\hyxmp@text{%
+      \StringEncodingConvert
+      \hyxmp@text\hyxmp@text{utf16be}{utf32be}%
+    }{%
+      \ifxetex
+        \hyxmp@xetex@crap
+      \else
+        \StringEncodingConvert
+        \hyxmp@text\hyxmp@text{pdfdoc}{utf32be}%
+      \fi
+    }%
+%    \end{macrocode}
+% \acro{UTF-32BE}~$\rightarrow$ \acro{UTF-32BE} as hex string
+%    \begin{macrocode}
+    \EdefEscapeHex\hyxmp@text{\hyxmp@text}%
+%    \end{macrocode}
+% \acro{UTF-32BE}~$\rightarrow$ \acro{XML} in \acro{ASCII}
+%    \begin{macrocode}
+    \edef\hyxmp@text{%
+      \expandafter
+    }\expandafter\hyxmp@toxml@unicodetex\hyxmp@text
+    \relax\relax\relax\relax\relax\relax\relax\relax
+  \else
+%    \end{macrocode}
+% \term{PDFDocEncoding}/\term{Unicode}~$\rightarrow$ \acro{UTF-8}
+%    \begin{macrocode}
+    \hyxmp@is@unicode\hyxmp@text{%
+      \StringEncodingConvert
+      \hyxmp@text\hyxmp@text{utf16be}{utf8}%
+    }{%
+      \StringEncodingConvert
+      \hyxmp@text\hyxmp@text{pdfdoc}{utf8}%
+    }%
+%    \end{macrocode}
+% \acro{UTF-8}~$\rightarrow$ \acro{UTF-8} as hex string
+%    \begin{macrocode}
+    \EdefEscapeHex\hyxmp@text{\hyxmp@text}%
+%    \end{macrocode}
+% \acro{UTF-8} as hex string~$\rightarrow$ \acro{XML} in \acro{UTF-8}
+% as hex string
+%    \begin{macrocode}
+    \edef\hyxmp@text{%
+      \expandafter\hyxmp@toxml\hyxmp@text\@empty\@empty
+    }%
+%    \end{macrocode}
+% \acro{XML} in \acro{UTF-8} as hex string~$\rightarrow$ \acro{XML}
+% in \acro{UTF-8}
+%    \begin{macrocode}
+    \EdefUnescapeHex\hyxmp@text{\hyxmp@text}%
+  \fi
+  \global\let\hyxmp@xmlified\hyxmp@text
+}
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\hyxmp@is@unicode}
+% \changes{v2.0}{2012/08/02}{Added by Heiko Oberdiek}
+% \begin{macro}{\hyxmp@@is@unicode}
+% Given a string and two expressions, evaluate the first expression if
+% the string is \acro{UTF-16BE}-encoded and the second expression if not.
+%    \begin{macrocode}
+\begingroup
+  \lccode`\<=254 %
+  \lccode`\>=255 %
+  \catcode254=12 %
+  \catcode255=12 %
+\lowercase{\endgroup
+  \def\hyxmp@is@unicode#1{%
+    \expandafter\hyxmp@@is@unicode#1<>\@nil
+  }%
+  \def\hyxmp@@is@unicode#1<>#2\@nil{%
+    \ifx\\#1\\%
+      \expandafter\@firstoftwo
+    \else
+      \expandafter\@secondoftwo
+    \fi
+  }%
+}
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\hyxmp@toxml}
+% \changes{v2.0}{2012/08/02}{Added by Heiko Oberdiek}
+% Replace the characters ``\textless'', ``\&'', and ``\textgreater'' with
+% \acro{XML} entities when using a non-native-\term{Unicode}
+% \tex\ (\tex\ or \pdfTeX).
+%    \begin{macrocode}
+\def\hyxmp@toxml#1#2{%
+  \ifx#1\@empty
+  \else
+    \ifnum"#1#2=`\& %
+      26616D703B% &amp;
+    \else\ifnum"#1#2=`\< %
+      266C743B% &lt;
+    \else\ifnum"#1#2=`\> %
+      2667743B% &gt;
+    \else
+%    \end{macrocode}
+% \cmdname{dvips} wraps text when generating most PostScript code but
+% preserves line breaks within strings.  Unfortunately, \cmdname{dvips}
+% fails to observe the special case in the PostScript specification that
+% ``[b]alanced pairs of parentheses in the string require no special
+% treatment''~\cite{Adobe1996:postscript}.  Consequently, \acro{XMP}
+% data containing parentheses (e.g.,~``\texttt{Copyright (C) 1605 Miguel
+%   de Cervantes}'') confuse \cmdname{dvips} into thinking that the
+% string has ended after the closing parenthesis and that line breaks
+% can subsequently be injected safely into the document at arbitrary
+% points for formatting purposes.  This leads to erroneous display by
+% \acro{PDF} viewers, which honor line breaks within \acro{XMP} tags.
+% The solution is to insert a backslash before all parentheses when in
+% \texttt{pdfmark}-generating mode to convince \cmdname{dvips} that the
+% entire \acro{XMP} packet must be treated as a single,
+% not-to-be-modified string.
+% \changes{v2.0}{2012/08/22}{Escaped parentheses written with
+%   \texttt{pdfmark}s to prevent \cmdname{dvips} from line-wrapping the
+%   \protect\acro{XMP} packet}
+%    \begin{macrocode}
+      \@ifundefined{pdfmark}{%
+        #1#2%
+      }{%
+      \ifnum"#1#2=`\( %
+        5C28% \(
+      \else\ifnum"#1#2=`\) %
+        5C29% \)
+      \else
+        #1#2%
+      \fi\fi
+      }%
+    \fi\fi\fi
+    \expandafter\hyxmp@toxml
+  \fi
+}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\hyxmp@toxml@unicodetex}
+% \changes{v2.0}{2012/08/02}{Added by Heiko Oberdiek}
+% \begin{macro}{\hyxmp@text}
+% Replace the characters ``\textless'', ``\&'', and ``\textgreater'' with
+% \acro{XML} entities when using a native-\term{Unicode}
+% \tex\ (\XeTeX\ or \LuaTeX).
+%    \begin{macrocode}
+\def\hyxmp@toxml@unicodetex#1#2#3#4#5#6#7#8{%
+  \ifx#1\relax
+  \else
+    \ifnum"#1#2#3#4#5#6#7#8>127 %
+      \uccode`\*="#1#2#3#4#5#6#7#8\relax
+      \uppercase{%
+        \edef\hyxmp@text{\hyxmp@text *}%
+      }%
+    \else\ifnum"#7#8=`\< %
+      \edef\hyxmp@text{\hyxmp@text &lt;}%
+    \else\ifnum"#7#8=`\& %
+      \edef\hyxmp@text{\hyxmp@text &amp;}%
+    \else\ifnum"#7#8=`\> %
+      \edef\hyxmp@text{\hyxmp@text &gt;}%
+    \else\ifnum"#7#8=`\ %
+      \edef\hyxmp@text{\hyxmp@text\space}%
+    \else
+      \uccode`\*="#7#8\relax
+      \uppercase{%
+        \edef\hyxmp@text{\hyxmp@text *}%
+      }%
+    \fi\fi\fi\fi\fi
+    \expandafter\hyxmp@toxml@unicodetex
+  \fi
+}
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\hyxmp@skipzeros}
+% \changes{v2.0}{2012/08/02}{Added by Heiko Oberdiek}
+% Skip over leading zeroes in the input argument.
+%    \begin{macrocode}
+\def\hyxmp@skipzeros#1{%
+  \ifx#10%
+    \expandafter\hyxmp@skipzeros
+  \fi
+}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\x}
+% \begin{macro}{\hyxmp@xetex@crap}
+% \changes{v2.0}{2012/08/02}{Added by Heiko Oberdiek}
+% \begin{macro}{\hyxmp@try}
+% \begin{macro}{\hyxmp@crap@result}
+% \begin{macro}{\hyxmp@text}
+% In the case of \XeTeX, the strings defined by |\pdfstringdef| can
+% contain big characters.  In this case, the string is treated as
+% \term{Unicode}.
+%    \begin{macrocode}
+\begingroup
+\def\x#1{\endgroup
+  \def\hyxmp@xetex@crap{%
+    \edef\hyxmp@try{%
+      \expandafter\hyxmp@SpaceOther\hyxmp@text#1\@nil
+    }%
+    \let\hyxmp@crap@result=N%
+    \expandafter\hyxmp@crap@test\hyxmp@try\relax
+    \ifx\hyxmp@crap@result Y%
+      \let\hyxmp@text\@empty
+      \expandafter\hyxmp@crap@convert\hyxmp@try\relax
+    \else
+      \StringEncodingConvert\hyxmp@text\hyxmp@text{pdfdoc}{utf32be}%
+    \fi
+  }%
+}
+\x{ }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\hyxmp@SpaceOther}
+% Re-encode all spaces in a string with category code~12 (``other'').
+% \changes{v2.0}{2012/08/02}{Added by Heiko Oberdiek}
+%    \begin{macrocode}
+\begingroup
+  \catcode`\~=12 %
+  \lccode`\~=`\ %
+\lowercase{\endgroup
+  \def\hyxmp@SpaceOther#1 #2\@nil{%
+    #1%
+    \ifx\relax#2\relax
+      \expandafter\@gobble
+    \else
+      ~%
+      \expandafter\@firstofone
+    \fi
+    {\hyxmp@SpaceOther#2\@nil}%
+  }%
+}
+%    \end{macrocode}
+% \end{macro}
+%
+%
+% \begin{macro}{\hyxmp@crap@test}
+% Determine if we need to treat a string as \term{Unicode}.
+% \changes{v2.0}{2012/08/02}{Added by Heiko Oberdiek}
+%    \begin{macrocode}
+\def\hyxmp@crap@test#1{%
+  \ifx#1\relax
+  \else
+    \ifnum`#1>127 %
+      \let\hyxmp@crap@result=Y%
+      \expandafter\expandafter\expandafter\hyxmp@skiptorelax
+    \else
+      \expandafter\expandafter\expandafter\hyxmp@crap@test
+    \fi
+  \fi
+}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\hyxmp@skiptorelax}
+% Discard all tokens up to and including the first |\relax|.
+% \changes{v2.0}{2012/08/02}{Added by Heiko Oberdiek}
+%    \begin{macrocode}
+\def\hyxmp@skiptorelax#1\relax{}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\hyxmp@crap@convert}
+% \changes{v2.0}{2012/08/02}{Added by Heiko Oberdiek}
+% \begin{macro}{\hyxmp@num}
+% \begin{macro}{\hyxmp@text}
+% Convert a hexadecimal string to a number.
+%    \begin{macrocode}
+\def\hyxmp@crap@convert#1{%
+  \ifx#1\relax
+  \else
+    \edef\hyxmp@num{\number`#1}%
+    \ifnum\hyxmp@num>"FFFFFF %
+      \lccode`\!=\intcalcDiv{\hyxmp@num}{\number"1000000}\relax
+      \lowercase{\edef\hyxmp@text{\hyxmp@text!}}%
+      \edef\hyxmp@num{\intcalcMod{\hyxmp@num}{\number"1000000}}%
+    \else
+      \edef\hyxmp@text{\hyxmp@text\hyxmp@zero}%
+    \fi
+    \ifnum\hyxmp@num>"FFFF %
+      \lccode`\!=\intcalcDiv{\hyxmp@num}{\number"10000}\relax
+      \lowercase{\edef\hyxmp@text{\hyxmp@text!}}%
+      \edef\hyxmp@num{\intcalcMod{\hyxmp@num}{\number"10000}}%
+    \else
+      \edef\hyxmp@text{\hyxmp@text\hyxmp@zero}%
+    \fi
+    \ifnum\hyxmp@num>"FF %
+      \lccode`\!=\intcalcDiv{\hyxmp@num}{\number"100}\relax
+      \lowercase{\edef\hyxmp@text{\hyxmp@text!}}%
+      \edef\hyxmp@num{\intcalcMod{\hyxmp@num}{\number"100}}%
+    \else
+      \edef\hyxmp@text{\hyxmp@text\hyxmp@zero}%
+    \fi
+    \ifnum\hyxmp@num>0 %
+      \lccode`\!=\hyxmp@num\relax
+      \lowercase{\edef\hyxmp@text{\hyxmp@text!}}%
+    \else
+      \edef\hyxmp@text{\hyxmp@text\hyxmp@zero}%
+    \fi
+    \expandafter\hyxmp@crap@convert
+  \fi
+}
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\hyxmp@zero}
+% Define a null character with category code~12 (``other'').
+% \changes{v2.0}{2012/08/02}{Added by Heiko Oberdiek}
+%    \begin{macrocode}
+\begingroup
+  \catcode0=12 %
+  \gdef\hyxmp@zero{^^00}%
+\endgroup
+%    \end{macrocode}
+% \end{macro}
+%
+%
+% \subsubsection{Providing metadata in multiple languages}
+% \label{sec:lang-alt}
+%
+% Certain \acro{XMP} tags---\xmpprop{dc:title},
+% \xmpprop{dc:description}, and \xmpprop{dc:rights} (and others?  Let me
+% know.)---can be expressed in multiple languages.  The same text is
+% used for both language \optname{pdfmetalang} (default:
+% \optname{pdflang}) and language ``|x-default|''.  To express the same
+% metadata in multiple languages, we provide an |\XMPLangAlt| macro to
+% construct a list of alternative forms for a piece of metadata.
+%
+% \begin{macro}{\hyxmp@alt@title}
+% \begin{macro}{\hyxmp@alt@description}
+% \begin{macro}{\hyxmp@alt@rights}
+% Each of these macros is a list in which each element is of the form
+% ``|\do| \meta{language} \meta{text}'' in which \meta{language} is an
+% \acro{ISO} \mbox{639-1} two-letter country code with an optional
+% \acro{ISO} \mbox{3166-1} two-letter region code.  For example,
+% |\hyxmp@alt@title| may contain an element, ``|\do| |{es-MX}|
+% |{Este| |es| |mi| |documento}|''.
+%    \begin{macrocode}
+\def\hyxmp@alt@title{}
+\def\hyxmp@alt@description{}
+\def\hyxmp@alt@rights{}
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\hyxmp@LA@accept}
+% This macro wraps |\define@key| to make the option ``|#1|=\meta{value}''
+% append \meta{value} to list~|#2|.
+%    \begin{macrocode}
+\newcommand{\hyxmp@LA@accept}[2]{%
+  \define@key{hyxmp@LA}{#1}{%
+%    \end{macrocode}
+% \begin{macro}{\hyxmp@value}
+% As Niklas Beisert observed, if the option passed to the current key
+% contains \LaTeX\ code, this code will be included in the \acro{XMP}
+% packet, which is undesirable.  Hence, we first clean up the string
+% using |\hyxmp@pdfstringdef|.
+%    \begin{macrocode}
+    \hyxmp@pdfstringdef\hyxmp@value{##1}%
+    \xdef#2{#2\noexpand\do {\hyxmp@cur@lang} {\hyxmp@value}}%
+  }
+}
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% Define \meta{key}=\meta{value} options for appending to each of the
+% |\hyxmp@alt|\meta{tag} lists.
+%    \begin{macrocode}
+\hyxmp@LA@accept{pdftitle}{\hyxmp@alt@title}
+\hyxmp@LA@accept{pdfsubject}{\hyxmp@alt@description}
+\hyxmp@LA@accept{pdfcopyright}{\hyxmp@alt@rights}
+%    \end{macrocode}
+%
+% \begin{macro}{\XMPLangAlt}
+% Argument~|#1| is a language expressed as a two-letter country code and
+% optional two-letter region code.  Argument~|#2| is a list of
+% \meta{key}=\meta{value} pairs.  Keys correspond to |\hypersetup|
+% options such as ``|pdftitle|'', ``|pdfsubject|'', and
+% ``|pdfcopyright|''.  Values are the alternative-language form of the
+% text provided for the corresponding option.
+% \changes{v3.3}{2017/07/22}{Added this macro based on a request---and
+%   some code---by Niklas Beisert to support metadata expressed in multiple
+%   languages}
+%    \begin{macrocode}
+\newcommand{\XMPLangAlt}[2]{%
+  \let\do=\relax
+%    \end{macrocode}
+% \begin{macro}{\hyxmp@cur@lang}
+% Store the provided language, which will be used during option processing.
+%    \begin{macrocode}
+  \edef\hyxmp@cur@lang{#1}%
+  \setkeys{hyxmp@LA}{#2}%
+}
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+%
+% \subsection{UUID generation}
+% \label{sec:uuid-gen}
+%
+% We use a linear congruential generator to produce pseudorandom
+% version~4 \acro{UUID}s~\cite{Leach2005:uuid}.  True, this method has
+% its flaws but it's simple to implement in \tex\ and is good enough for
+% producing the \acro{XMP} \xmpprop{xmpMM:DocumentID} and
+% \xmpprop{xmpMM:InstanceID} fields.
+%
+% \begin{macro}{\hyxmp@modulo@a}
+% Replace the contents of |\@tempcnta| with the contents modulo~|#1|.
+% Note that |\@tempcntb| is overwritten in the process.
+%    \begin{macrocode}
+\def\hyxmp@modulo@a#1{%
+  \@tempcntb=\@tempcnta
+  \divide\@tempcntb by #1
+  \multiply\@tempcntb by #1
+  \advance\@tempcnta by -\@tempcntb
+}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\hyxmp@big@prime}
+% \begin{macro}{\hyxmp@big@prime@ii}
+% Define a couple of large prime numbers that can still be stored in a
+% \tex\ counter.
+%    \begin{macrocode}
+\def\hyxmp@big@prime{536870923}
+\def\hyxmp@big@prime@ii{536870027}
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\hyxmp@seed@rng}
+% \begin{macro}{\hyxmp@one@token}
+% Seed \pkgname{hyperxmp}'s random-number generator from a given piece
+% of text.
+%    \begin{macrocode}
+\def\hyxmp@seed@rng#1{%
+  \@tempcnta=\hyxmp@big@prime
+  \futurelet\hyxmp@one@token\hyxmp@seed@rng@i#1\@empty
+}
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\hyxmp@seed@rng@i}
+% \begin{macro}{\hyxmp@one@token}
+% \begin{macro}{\next}
+% Do all of the work for |\hyxmp@seed@rng|.  For each character code $c$
+% of the input text, assign $\mathtt{\string\@tempcnta} \leftarrow 3
+% \cdot \mathtt{\string\@tempcnta} + c
+% \pmod{\mathtt{\string\hyxmp@big@prime}}$.
+%    \begin{macrocode}
+\def\hyxmp@seed@rng@i{%
+  \ifx\hyxmp@one@token\@empty
+    \let\next=\relax
+  \else
+    \def\next##1{%
+      \multiply\@tempcnta by 3
+      \advance\@tempcnta by `##1
+      \hyxmp@modulo@a{\hyxmp@big@prime}%
+      \futurelet\hyxmp@one@token\hyxmp@seed@rng@i
+    }%
+  \fi
+  \next
+}
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\hyxmp@set@rand@num}
+% \begin{macro}{\hyxmp@rand@num}
+% Advance |\hyxmp@rand@num| to the next pseudorandom number in the
+% sequence.  Specifically, we assign $\mathtt{\string\hyxmp@rand@num}
+% \leftarrow 3 \cdot \mathtt{\string\hyxmp@rand@num} +
+% \mathtt{\string\hyxmp@big@prime@ii}
+% \pmod{\mathtt{\string\hyxmp@big@prime}}$.  Note that both |\@tempcnta|
+% and |\@tempcntb| are overwritten in the process.
+%    \begin{macrocode}
+\def\hyxmp@set@rand@num{%
+  \@tempcnta=\hyxmp@rand@num
+  \multiply\@tempcnta by 3
+  \advance\@tempcnta by \hyxmp@big@prime@ii
+  \hyxmp@modulo@a{\hyxmp@big@prime}%
+  \xdef\hyxmp@rand@num{\the\@tempcnta}%
+}
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\hyxmp@append@hex}
+% Append a randomly selected hexadecimal digit to macro~|#1|.  Note that
+% both |\@tempcnta| and |\@tempcntb| are overwritten in the process.
+%    \begin{macrocode}
+\def\hyxmp@append@hex#1{%
+  \hyxmp@set@rand@num
+  \@tempcnta=\hyxmp@rand@num
+  \hyxmp@modulo@a{16}%
+  \ifnum\@tempcnta<10
+    \xdef#1{#1\the\@tempcnta}%
+  \else
+%    \end{macrocode}
+% There \emph{must} be a better way to handle the numbers~10--15 than
+% with |\ifcase|.
+%    \begin{macrocode}
+    \advance\@tempcnta by -10
+    \ifcase\@tempcnta
+      \xdef#1{#1a}%
+      \or\xdef#1{#1b}%
+      \or\xdef#1{#1c}%
+      \or\xdef#1{#1d}%
+      \or\xdef#1{#1e}%
+      \or\xdef#1{#1f}%
+    \fi
+  \fi
+}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\hyxmp@append@hex@iii}
+% Invoke |\hyxmp@append@hex| three times.
+%    \begin{macrocode}
+\def\hyxmp@append@hex@iii#1{%
+  \hyxmp@append@hex#1%
+  \hyxmp@append@hex#1%
+  \hyxmp@append@hex#1%
+}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\hyxmp@append@hex@iv}
+% Invoke |\hyxmp@append@hex| four times.
+%    \begin{macrocode}
+\def\hyxmp@append@hex@iv#1{%
+  \hyxmp@append@hex@iii#1%
+  \hyxmp@append@hex#1%
+}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\hyxmp@create@uuid}
+% As per the definition of a version~4
+% \acro{UUID}~\cite{Leach2005:uuid}, define macro~|#1| as a \acro{UUID}
+% of the form
+% ``|uuid:|\textit{xxxxxxxx}|-|\linebreak[0]\textit{xxxx}|-|\linebreak[0]\textit{4xxx}|-|\linebreak[0]\textit{yxxx}|-|\linebreak[0]\textit{xxxxxxxxxxxx}''
+% in which each ``\textit{x}'' is a lowercase hexadecimal digit and
+% ``\textit{y}'' is one of ``|8|'', ``|9|'', ``|a|'', or~``|b|''.  We
+% assume that the random-number generator is already seeded.  Note that
+% |\hyxmp@create@uuid| overwrites both |\@tempcnta| and |\@tempcntb|.
+% \changes{v2.4}{2014/01/02}{Modified this macro to produce a proper
+%   version~4 (random or pseudorandom) \protect\acro{UUID}}
+%    \begin{macrocode}
+\def\hyxmp@create@uuid#1{%
+  \def#1{uuid:}%
+  \hyxmp@append@hex@iv#1%
+  \hyxmp@append@hex@iv#1%
+  \g@addto@macro#1{-}%
+  \hyxmp@append@hex@iv#1%
+  \g@addto@macro#1{-4}%
+  \hyxmp@append@hex@iii#1%
+  \g@addto@macro#1{-}%
+%    \end{macrocode}
+% Randomly select one of ``|8|'', ``|9|'', ``|a|'', or~``|b|''.
+%    \begin{macrocode}
+  \hyxmp@set@rand@num
+  \@tempcnta=\hyxmp@rand@num
+  \hyxmp@modulo@a{4}%
+  \ifcase\@tempcnta
+    \g@addto@macro#1{8}%
+    \or\g@addto@macro#1{9}%
+    \or\g@addto@macro#1{a}%
+    \or\g@addto@macro#1{b}%
+  \fi
+  \hyxmp@append@hex@iii#1%
+  \g@addto@macro#1{-}%
+  \hyxmp@append@hex@iv#1%
+  \hyxmp@append@hex@iv#1%
+  \hyxmp@append@hex@iv#1%
+}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\hyxmp@def@DocumentID}
+% \begin{macro}{\hyxmp@DocumentID}
+% \begin{macro}{\hyxmp@seed@string}
+% Seed the random-number generator with a function of the current
+% filename, \acro{PDF} document title, and \acro{PDF} author, then invoke
+% |\hyxmp@create@uuid| to define |\hyxmp@DocumentID| as a random \acro{UUID}.
+% \changes{v3.4}{2017/11/04}{Correctly handle an author field of all spaces.
+%   Bug reported by Ga\"etan Leurent}
+%    \begin{macrocode}
+\newcommand*{\hyxmp@def@DocumentID}{%
+  \edef\hyxmp@seed@string{\jobname:\@pdftitle:\@pdfauthor:}%
+  \expandafter\hyxmp@seed@rng\expandafter{\hyxmp@seed@string}%
+  \edef\hyxmp@rand@num{\the\@tempcnta}%
+  \hyxmp@create@uuid\hyxmp@DocumentID
+}
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\hyxmp@def@InstanceID}
+% \begin{macro}{\hyxmp@InstanceID}
+% \begin{macro}{\hyxmp@seed@string}
+% Seed the random-number generator with a function of the current
+% filename, \acro{PDF} document title, \acro{PDF} author, and the
+% current timestamp, then invoke |\hyxmp@create@uuid| to define
+% |\hyxmp@InstanceID| as a random \acro{UUID}.  For the current
+% timestamp, we use both the document-specified timestamp from
+% \optname{pdfdate} and the \tex\ time.  The former can be more precise
+% (to sub-seconds) but may be less random (as it depends on manual
+% document modifications) while the latter is typically less precise (to
+% minutes) but may be more random (as it is updated automatically).
+% \changes{v3.5}{2018/11/27}{Seed with the \protect\TeX\ timestamp in
+%   addition to the document-specified timestamp}
+%    \begin{macrocode}
+\newcommand*{\hyxmp@def@InstanceID}{%
+  \hyxmp@today@define{\hyxmp@seed@string}%
+  \edef\hyxmp@seed@string{%
+    \jobname:\@pdftitle:\@pdfauthor:\hyxmp@today:\hyxmp@seed@string
+  }%
+  \expandafter\hyxmp@seed@rng\expandafter{\hyxmp@seed@string}%
+  \edef\hyxmp@rand@num{\the\@tempcnta}%
+  \hyxmp@create@uuid\hyxmp@InstanceID
+}
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+%
+% \subsection{Constructing the XMP packet}
+%
+% An \acro{XMP} packet ``shall consist of the following, in order: a
+% header \acro{PI}, the serialized \acro{XMP} data model (the \acro{XMP}
+% packet) with optional white-space padding, and a trailer
+% \acro{PI}''~\cite{Adobe2012:XMP}.  (``\acro{PI}'' is an abbreviation
+% for ``processing instructions'').  The serialized \acro{XMP} includes
+% blocks of \acro{XML} for various \acro{XMP} schemata: Adobe \acro{PDF}
+% (Section~\ref{sec:adobe-pdf}), Dublin Core
+% (Section~\ref{sec:dublin-core}), \acro{XMP} Rights Management
+% (Section~\ref{sec:xmp-rights}), \acro{XMP} Media Management
+% (Section~\ref{sec:xmp-media}), \acro{XMP} Basic
+% (Section~\ref{sec:xmp-basic}), Photoshop
+% (Section~\ref{sec:photoshop}), \acro{IPTC} Photo Metadata
+% (Section~\ref{sec:photo-meta}), and \acro{PDF/A} Identification
+% (Section~\ref{sec:pdfa-id}).  The |\hyxmp@construct@packet| macro
+% (Section~\ref{sec:combining-schemata}) constructs the \acro{XMP}
+% packet into |\hyxmp@xml|.  It first writes the appropriate \acro{XML}
+% header, then calls the various schema-writing macros, then injects
+% |\hyxmp@padding| as padding, and finally writes the appropriate
+% \acro{XML} trailer.
+%
+% \subsubsection{XMP utility functions}
+%
+% \begin{macro}{\hyxmp@add@to@xml}
+% Given a piece of text, replace all underscores with category-code~11
+% (``other'') spaces and all |^C| characters with commas, then append
+% the result to the |\hyxmp@xml| macro.
+% \changes{v2.0}{2012/08/24}{Updated also to replace commas}
+% \changes{v2.5}{2014/06/19}{Updated also to replace underscores and to
+%   modify only the text being added, not the already-modified text}
+% \changes{v2.8}{2014/04/05}{Corrected inadvertent lowercasing of non-Latin
+%   characters when run under \XeLaTeX\ or \LuaLaTeX\ (bug reported by
+%   Leonid Sinev)}
+%    \begin{macrocode}
+\newcommand*{\hyxmp@add@to@xml}[1]{%
+  \bgroup
+    \@tempcnta=0
+    \ifhyxmp@unicodetex
+      \@tempcntb=65536%
+    \else
+      \@tempcntb=256%
+    \fi
+    \loop
+      \lccode\@tempcnta=\@tempcnta
+      \advance\@tempcnta by 1
+      \ifnum\@tempcnta<\@tempcntb
+    \repeat
+    \lccode`\_=`\ \relax
+    \lccode`\^^C=`\,\relax
+    \lccode`\^^U=`\_\relax
+    \lowercase{\xdef\hyxmp@new@xml{#1}}%
+    \xdef\hyxmp@xml{\hyxmp@xml\hyxmp@new@xml}%
+  \egroup
+}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\hyxmp@hash}
+% Define a category-code~11 (``other'') version of the ``|#|'' character.
+%    \begin{macrocode}
+\bgroup
+\catcode`\#=11
+\gdef\hyxmp@hash{#}
+\egroup
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\hyxmp@padding}
+% \begin{macro}{\hyxmp@xml}
+% The \acro{XMP} specification recommends leaving approximately
+% 2000~bytes of whitespace at the end of each \acro{XMP} packet to
+% facilitate editing the packet in place~\cite{Adobe2012:XMP}.
+% |\hyxmp@padding| is defined to contain 32~lines of 63~spaces and a
+% newline apiece for a total of 2048 characters of whitespace.
+%    \begin{macrocode}
+\bgroup
+  \xdef\hyxmp@xml{}%
+  \hyxmp@add@to@xml{%
+_______________________________________________________________^^J%
+  }
+  \xdef\hyxmp@padding{\hyxmp@xml}%
+\egroup
+\xdef\hyxmp@padding{\hyxmp@padding\hyxmp@padding}
+\xdef\hyxmp@padding{\hyxmp@padding\hyxmp@padding}
+\xdef\hyxmp@padding{\hyxmp@padding\hyxmp@padding}
+\xdef\hyxmp@padding{\hyxmp@padding\hyxmp@padding}
+\xdef\hyxmp@padding{\hyxmp@padding\hyxmp@padding}
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\hyxmp@x@default}
+% Define an |x-default| string that we can use in comparisons with
+% |\@pdfmetalang|.
+%    \begin{macrocode}
+\newcommand*{\hyxmp@x@default}{x-default}
+%    \end{macrocode}
+% \end{macro}
+%
+%
+% \subsubsection{The Adobe PDF schema}
+% \label{sec:adobe-pdf}
+%
+% \begin{macro}{\hyxmp@pdf@schema}
+% Add properties defined by the Adobe \acro{PDF} schema to the |\hyxmp@xml|
+% macro.
+%    \begin{macrocode}
+\newcommand*{\hyxmp@pdf@schema}{%
+%    \end{macrocode}
+% Add a block of \acro{XML} to |\hyxmp@xml| that lists the document's
+% keywords (the \xmpprop{pdf:Keywords} property), the tools used to
+% produce the \acro{PDF} file (the \xmpprop{pdf:Producer} property), and
+% the version of the \acro{PDF} standard adhered to (the
+% \xmpprop{pdf:PDFVersion} property).  Unlike most of the other schemata
+% that \pkgname{hyperxmp} supports, the Adobe \acro{PDF} schema is
+% \emph{always} included in the document, even if all of its keys are
+% empty.  This is because \acro{PDF/A}-1b requires the keywords and
+% producer to be the same in the \acro{XMP} metadata and the \acro{PDF}
+% metadata.  Because \pkgname{hyperref} always specifies the
+% \pdfterm{Keywords} and \pdfterm{Producer} fields, even when they're
+% empty, \pkgname{hyperxmp} has to follow suit and define
+% \xmpprop{pdf:Keywords} and \xmpprop{pdf:Producer} in the \acro{XMP}
+% packet.
+% \changes{v2.4}{2013/12/21}{Made
+%   \texttt{\string\string\string\hyxmp@pdf@schema}
+%   \protect\emph{always} include the Adobe \protect\acro{PDF} schema,
+%   even when empty.  Florian Breitwieser noted that this is necessary
+%   for \protect\acro{PDF/A}-1b compliance}
+%    \begin{macrocode}
+  \hyxmp@add@simple@var{pdf:Keywords}{@pdfkeywords}%
+  \hyxmp@add@simple@var{pdf:Producer}{@pdfproducer}%
+  \@ifundefined{pdfvariable}{%
+    \@ifundefined{pdfminorversion}{%
+%    \end{macrocode}
+% Case 1: Neither |\pdfvariable| nor |\pdfminorversion| is defined
+% (\XeLaTeX\ and regular \LaTeX).
+%    \begin{macrocode}
+    }{%
+%    \end{macrocode}
+% Case 2: |\pdfminorversion| is defined (\pdfLaTeX\ and pre-0.85 \LuaLaTeX).
+%    \begin{macrocode}
+      \hyxmp@add@simple{pdf:PDFVersion}{1.\the\pdfminorversion}%
+    }%
+  }{%
+%    \end{macrocode}
+% Case 3: |\pdfvariable| is defined (\LuaLaTeX~0.85+).
+%    \begin{macrocode}
+    \hyxmp@add@simple{pdf:PDFVersion}{1.\the\pdfvariable minorversion}%
+  }%
+}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\hyxmp@extra@indent}
+% This macro is used internally to increase the amount of indentation
+% when writing certain \acro{XML} data.  It is normally defined as empty
+% but can temporarily be redefined to a sequence of |\space| characters.
+%    \begin{macrocode}
+\newcommand*{\hyxmp@extra@indent}{}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\hyxmp@add@simple}
+% Given an \acro{XMP} tag~(|#1|) and a string~(|#2|), if the string is
+% nonempty, add a begin tag, the string, and an end tag to the packet.
+% The ``|simple|'' in the macro name indicates that the string is output
+% without variations for different languages.
+% \changes{v2.0}{2012/08/25}{Added this macro}
+%    \begin{macrocode}
+\newcommand*{\hyxmp@add@simple}[2]{%
+  \@ifnotmtargexp{#2}{%
+    \hyxmp@xmlify{#2}%
+    \hyxmp@add@to@xml{%
+      \hyxmp@extra@indent______<#1>\hyxmp@xmlified</#1>^^J%
+    }%
+  }%
+}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\hyxmp@add@simple@var}
+% Given an \acro{XMP} tag~(|#1|) and a variable name~(|#2|), if the
+% string is defined, add a begin tag, the string, and an end tag to the
+% packet.  The ``|simple|'' in the macro name indicates that the string
+% is output without variations for different languages.
+% |\hyxmp@add@simple@var| differs from |\hyxmp@add@simple| in that the
+% former includes defined but empty values in the \acro{XMP} packet
+% while the latter excludes both undefined and defined but empty values.
+% \changes{v2.4}{2013/12/21}{Added this macro}
+%    \begin{macrocode}
+\newcommand*{\hyxmp@add@simple@var}[2]{%
+  \expandafter\ifx\csname#2\endcsname\relax
+  \else
+    \hyxmp@xmlify{\csname#2\endcsname}%
+    \hyxmp@add@to@xml{%
+      \hyxmp@extra@indent______<#1>\hyxmp@xmlified</#1>^^J%
+    }%
+  \fi
+}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\hyxmp@add@simple@lang}
+% Given an \acro{XMP} tag~(|#1|) and a string~(|#2|), if the string is
+% nonempty, add a begin tag, the string, and an end tag to the packet.
+% The ``|simple|'' in the macro name indicates that the string is output
+% without variations for different languages.  However, if the string
+% begins with a language code in square brackets, specify that as the
+% (sole) language for the tag.
+% \changes{v4.0}{2019/03/12}{Added this macro}
+%    \begin{macrocode}
+\newcommand*{\hyxmp@add@simple@lang}[2]{%
+  \@ifnotmtarg{#2}{%
+    \hyxmp@xmlify{#2}%
+    \expandafter\hyxmp@add@simple@lang@i\hyxmp@xmlified\relax{#1}%
+  }%
+}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\hyxmp@add@simple@lang@i}
+% This is a helper macro for |\hyxmp@add@simple@lang|.  It takes an
+% optional language code (in brackets), text up to |\relax|, and a tag,
+% and typesets the text within the \acro{XML} tag.
+%    \begin{macrocode}
+\newcommand*{\hyxmp@add@simple@lang@i}{%
+  \@ifnextchar[\hyxmp@add@simple@lang@ii{\hyxmp@add@simple@lang@ii[]}%
+}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\hyxmp@add@simple@lang@ii}
+% This is another helper macro for |\hyxmp@add@simple@lang|.  It takes
+% an mandatory language code (in brackets; can be empty), text up to
+% |\relax|, and a tag, and typesets the text within the \acro{XML} tag.
+%    \begin{macrocode}
+\def\hyxmp@add@simple@lang@ii[#1]#2\relax#3{%
+  \@ifnotmtarg{#2}{%
+    \hyxmp@xmlify{#2}%
+    \@ifmtarg{#1}{%
+      \hyxmp@add@to@xml{%
+______<#3>\hyxmp@xmlified</#3>^^J%
+      }%
+    }{%
+      \hyxmp@add@to@xml{%
+______<#3 xml:lang="#1">\hyxmp@xmlified</#3>^^J%
+      }%
+    }%
+  }%
+}
+%    \end{macrocode}
+% \end{macro}
+%
+%
+% \subsubsection{The Dublin Core schema}
+% \label{sec:dublin-core}
+%
+% \begin{macro}{\hyxmp@rdf@dc}
+% Given an optional |\if|\meta{something} statement (|#1|), a Dublin Core
+% property~(|#2|) and a macro containing some |\pdfstringdef|-defined
+% text~(|#3|), append the appropriate block of \acro{XML} to the |\hyxmp@xml|
+% macro.
+% \changes{v1.4}{2011/06/12}{Included metadata in the \texttt{x-default}
+%   language regardless of the specified metadata language}
+% \changes{v3.3}{2017/07/22}{Bug fix: Output the metadata language as
+%   correct \noexpand\acro{XML} even when \noexpand\pkgname{hyperref} is
+%   loaded with the \noexpand\optname{unicode} option}
+%    \begin{macrocode}
+\newcommand*{\hyxmp@rdf@dc}[3][\iffalse]{%
+%    \end{macrocode}
+% Set |\@tempswatrue| only if the given text is nonempty or the provided
+% conditional evaluates to \textsc{true}.
+%    \begin{macrocode}
+  \@ifmtargexp{#3}{\@tempswafalse}{\@tempswatrue}%
+  #1
+    \@tempswatrue
+  \fi
+%    \end{macrocode}
+% Append the corresponding \acro{XML} only if |\@tempswatrue|.
+%    \begin{macrocode}
+  \if@tempswa
+    \hyxmp@xmlify{#3}%
+%    \end{macrocode}
+% \begin{macro}{\hyxmp@value}
+% Store the \acro{XML}-ified version of |#3| in |\hyxmp@value| so we can
+% reuse |\hyxmp@xmlifiied| if necessary.
+%    \begin{macrocode}
+    \let\hyxmp@value=\hyxmp@xmlified
+    \hyxmp@add@to@xml{%
+______<dc:#2>^^J%
+________<rdf:Alt>^^J%
+    }%
+    \ifx\@pdfmetalang\hyxmp@x@default
+    \else
+      \hyxmp@xmlify{\@pdfmetalang}%
+      \hyxmp@add@to@xml{%
+__________<rdf:li xml:lang="\hyxmp@xmlified">\hyxmp@value</rdf:li>^^J%
+      }%
+    \fi
+    \hyxmp@add@to@xml{%
+__________<rdf:li xml:lang="\hyxmp@x@default">\hyxmp@value</rdf:li>^^J%
+    }%
+%    \end{macrocode}
+% Include variants of the text expressed in other languages, as specified by
+% the author using |\XMPLangAlt| (Section~\ref{sec:lang-alt}).
+%    \begin{macrocode}
+    \def\do##1##2{
+      \hyxmp@xmlify{##2}%
+      \hyxmp@add@to@xml{%
+__________<rdf:li xml:lang="##1">\hyxmp@xmlified</rdf:li>^^J%
+      }%
+    }%
+    \csname hyxmp@alt@#2\endcsname
+%    \end{macrocode}
+% Complete this \acro{XMP} element.
+%    \begin{macrocode}
+    \hyxmp@add@to@xml{%
+________</rdf:Alt>^^J%
+______</dc:#2>^^J%
+    }%
+  \fi
+}%
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\hyxmp@list@to@xml}
+% Given an optional |\if|\meta{something} statement (|#1|), a Dublin Core
+% property~(|#2|), an \acro{RDF} array~(|#3|), and a macro containing a
+% comma-separated list~(|#4|), append the appropriate block of \acro{XML} to
+% the |\hyxmp@xml| macro.
+% \changes{v2.0}{2012/08/02}{Modified by Heiko Oberdiek to use the new
+%   \term{Unicode}-processing macros}
+%    \begin{macrocode}
+\newcommand*{\hyxmp@list@to@xml}[4][\iffalse]{%
+%    \end{macrocode}
+% Set |\@tempswatrue| only if the given list is nonempty or the provided
+% conditional evaluates to \textsc{true}.
+%    \begin{macrocode}
+  \@ifmtargexp{#4}{\@tempswafalse}{\@tempswatrue}%
+  #1
+    \@tempswatrue
+  \fi
+%    \end{macrocode}
+% Append the corresponding \acro{XML} only if |\@tempswatrue|.
+%    \begin{macrocode}
+  \if@tempswa
+    \hyxmp@add@to@xml{%
+______<dc:#2>^^J%
+________<rdf:#3>^^J%
+    }%
+    \bgroup
+%    \end{macrocode}
+% \begin{macro}{\@elt}
+% Re-encode the text from \term{Unicode} if necessary.  Then redefine
+% |\@elt| to \acro{XML}-ify each element of the list and append it to
+% |\hyxmp@xmlified|.
+%    \begin{macrocode}
+      \hyxmp@xmlify{#4}%
+      \hyxmp@commas@to@list\hyxmp@list{\hyxmp@xmlified}%
+      \def\@elt##1{%
+        \hyxmp@add@to@xml{%
+__________<rdf:li>##1</rdf:li>^^J%
+        }%
+      }%
+      \hyxmp@list
+    \egroup
+    \hyxmp@add@to@xml{%
+________</rdf:#3>^^J%
+______</dc:#2>^^J%
+    }%
+  \fi
+}
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\hyxmp@singleton@dc}
+% Given an optional list type (|Seq| or |Bag|), a Dublin Core property,
+% and a string, append a block of \acro{XML} representing a one-element
+% list consisting of the given string.
+% \changes{v4.1}{2019/04/05}{Added this macro}
+%    \begin{macrocode}
+\newcommand{\hyxmp@singleton@dc}[3][Bag]{%
+  \@ifnotmtarg{#3}{%
+    \hyxmp@xmlify{#3}%
+    \hyxmp@add@to@xml{%
+______<dc:#2>^^J%
+________<rdf:#1>^^J%
+__________<rdf:li>\hyxmp@xmlified</rdf:li>^^J%
+________</rdf:#1>^^J%
+______</dc:#2>^^J%
+    }%
+  }
+}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\hyxmp@dc@schema}
+% Add properties defined by the Dublin Core schema to the |\hyxmp@xml|
+% macro.  Specifically, we add entries for the \xmpprop{dc:title}
+% property if the author specified a \optname{pdftitle}, the
+% \xmpprop{dc:description} property if the author specified a
+% \optname{pdfsubject}, the \xmpprop{dc:rights} property if the author
+% specified a \optname{pdfcopyright}, the \xmpprop{dc:creator} property
+% if the author specified a \optname{pdfauthor}, the
+% \xmpprop{dc:subject} property if the author specified
+% \optname{pdfkeywords}, and the \xmpprop{dc:language} property if the
+% author specified \optname{pdflang}.  We also specify the
+% \xmpprop{dc:date} property using the date the document was run through
+% \LaTeX\ and the \xmpprop{dc:source} property using the base name of
+% the source file with |.tex| appended.
+% \changes{v2.0}{2012/08/26}{Added support for \xmpprop{dc:language}
+%   and \xmpprop{dc:source}}
+% \changes{v2.4}{2013/12/21}{Made \xmpprop{dc:language} a \xmpterm{Bag}
+%   instead of an individual item so as to conform to the latest
+%   \acro{XMP} specifications, a detail identified by Florian Breitwieser}
+%    \begin{macrocode}
+\newcommand*{\hyxmp@dc@schema}{%
+  \hyxmp@add@simple{dc:format}{application/pdf}%
+  \hyxmp@rdf@dc[\ifHy@pdfa]{title}{\@pdftitle}%
+  \hyxmp@rdf@dc[\ifHy@pdfa]{description}{\@pdfsubject}%
+  \hyxmp@rdf@dc{rights}{\@pdfcopyright}%
+  \hyxmp@singleton@dc{publisher}{\@pdfpublisher}%
+  \hyxmp@singleton@dc[Seq]{date}{\hyxmp@today}%
+  \hyxmp@singleton@dc{language}{\@pdflang}%
+  \hyxmp@singleton@dc{type}{\@pdftype}%
+  \hyxmp@list@to@xml[\ifHy@pdfa]{creator}{Seq}{\hyxmp@pdfauthor}%
+  \hyxmp@list@to@xml{subject}{Bag}{\hyxmp@pdfkeywords}%
+  \ifx\@pdfsource\@empty
+  \else
+    \hyxmp@add@simple{dc:source}{\@pdfsource}%
+  \fi
+}
+%    \end{macrocode}
+% \end{macro}
+%
+% \subsubsection{The XMP Rights Management schema}
+% \label{sec:xmp-rights}
+%
+% \begin{macro}{\hyxmp@xmpRights@schema}
+% Add properties defined by the \acro{XMP} Rights Management schema to the
+% |\hyxmp@xml| macro.  Currently, these are only the
+% \xmpprop{xmpRights:Marked} property and the
+% \xmpprop{xmpRights:WebStatement} property.  If the author specified a
+% copyright statement we mark the document as copyrighted.  If the
+% author specified a license statement we include the \acro{URL} in the
+% metadata.
+% \changes{v1.4}{2011/05/29}{Renamed the \texttt{xapRights} namespace
+%   prefix to \texttt{xmpRights}}
+% \changes{v2.0}{2012/08/25}{Modified to include
+%   \xmpprop{xmpRights:Marked} only when \optname{pdfcopyright} is
+%   specified and \xmpprop{xmpRights:WebStatement} only when
+%   \optname{pdflicenseurl} is specified}
+%    \begin{macrocode}
+\newcommand*{\hyxmp@xmpRights@schema}{%
+%    \end{macrocode}
+% \begin{macro}{\hyxmp@legal}
+% Set |\hyxmp@rights| to |YES| if either \optname{pdfcopyright} or
+% \optname{pdflicenseurl} was specified.
+%    \begin{macrocode}
+  \let\hyxmp@rights=\@empty
+  \ifx\@pdflicenseurl\@empty
+  \else
+    \def\hyxmp@rights{YES}%
+  \fi
+  \ifx\@pdfcopyright\@empty
+  \else
+    \def\hyxmp@rights{YES}%
+  \fi
+%    \end{macrocode}
+% Include the license-statement \acro{URL} and/or the copyright
+% indication.  The copyright statement itself is included by
+% |\hyxmp@dc@schema| in Section~\ref{sec:dublin-core}.
+%    \begin{macrocode}
+  \ifx\hyxmp@rights\@empty
+  \else
+    \ifx\@pdfcopyright\@empty
+    \else
+      \hyxmp@add@simple{xmpRights:Marked}{True}%
+    \fi
+    \hyxmp@add@simple{xmpRights:WebStatement}{\@pdflicenseurl}%
+  \fi
+}
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+%
+% \subsubsection{The XMP Media Management schema}
+% \label{sec:xmp-media}
+%
+% \begin{macro}{\hyxmp@mm@schema}
+% Add properties defined by the \acro{XMP} Media Management schema to
+% the |\hyxmp@xml| macro.  According to the \acro{XMP} specification,
+% the \xmpprop{xmpMM:DocumentID} property is supposed to uniquely
+% identify a document, and the \xmpprop{xmpMM:InstanceID} property is
+% supposed to change with each save operation~\cite{Adobe2012:XMP}.  As
+% seen in Section~\ref{sec:uuid-gen}, we do what we can to honor this
+% intention from within a \tex-based workflow.  We additionally support
+% the \xmpprop{xmpMM:VersionID} property, whose value is supplied by
+% the author using \optname{pdfversionid}.
+% \changes{v1.4}{2011/05/29}{Renamed the \texttt{xapMM} namespace
+%   prefix to \texttt{xmpMM}}
+% \changes{v3.5}{2018/11/27}{Generate \protect\cs{hyxmp@DocumentID} and
+%   \protect\cs{hyxmp@InstanceID} only if the document does not already
+%   define these using the \protect\optname{pdfdocumentid} and
+%   \protect\optname{pdfinstanceid} options}
+% \changes{v4.0}{2019/03/09}{Include \protect\xmpprop{xmpMM:VersionID} in
+%   the \protect\acro{XMP} packet}
+%    \begin{macrocode}
+\gdef\hyxmp@mm@schema{%
+  \@ifmtargexp{\hyxmp@DocumentID}{\hyxmp@def@DocumentID}{}%
+  \@ifmtargexp{\hyxmp@InstanceID}{\hyxmp@def@InstanceID}{}%
+  \hyxmp@add@simple{xmpMM:DocumentID}{\hyxmp@DocumentID}%
+  \hyxmp@add@simple{xmpMM:InstanceID}{\hyxmp@InstanceID}%
+  \hyxmp@add@simple{xmpMM:VersionID}{\@pdfversionid}%
+}
+%    \end{macrocode}
+% \end{macro}
+%
+%
+% \subsubsection{The XMP Basic schema}
+% \label{sec:xmp-basic}
+%
+% \begin{macro}{\hyxmp@define@createdate}
+% \begin{macro}{\hyxmp@createdate}
+% Define |\hyxmp@createdate| as the document's creation date but in
+% \acro{XMP} date format, not \acro{PDF} date format.  We use
+% |\hyxmp@createdate| for the \xmpprop{xmp:CreateDate},
+% \xmpprop{xmp:ModifyDate}, and \xmpprop{xmp:MetadataDate} fields.
+%    \begin{macrocode}
+\newcommand*{\hyxmp@define@createdate}{%
+  \@ifundefined{pdffeedback}{%
+    \@ifundefined{pdfcreationdate}{%
+%    \end{macrocode}
+% Case 1: Neither |\pdffeedback| nor |\pdfcreationdate| is defined
+% (\XeLaTeX\ and regular \LaTeX).
+%    \begin{macrocode}
+      \hyxmp@today@define\hyxmp@createdate
+    }{%
+%    \end{macrocode}
+% Case 2: |\pdfcreationdate| is defined (\pdfLaTeX\ and pre-0.85 \LuaLaTeX).
+%    \begin{macrocode}
+      \edef\hyxmp@createdate{\expandafter\hyxmp@pdf@to@xmp@date\pdfcreationdate}%
+    }%
+  }{%
+%    \end{macrocode}
+% Case 3: |\pdffeedback| is defined (\LuaLaTeX~0.85+).
+%    \begin{macrocode}
+    \edef\hyxmp@createdate{\expandafter\hyxmp@pdf@to@xmp@date\pdffeedback creationdate}%
+  }%
+}
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\hyxmp@xmp@basic@schema}
+% Add properties defined by the \acro{XMP} Basic schema to the
+% |\hyxmp@xml| macro.  These include a bunch of dates (all set to the
+% same value) and the base \acro{URL} for the document if specified with
+% \optname{baseurl}.
+% \changes{v2.0}{2012/08/26}{Added this macro}
+% \changes{v3.0}{2016/07/04}{Made the \protect\acro{XMP}
+%   \protect\xmpprop{xmp:CreateDate}, \protect\xmpprop{xmp:ModifyDate},
+%   and \protect\xmpprop{xmp:MetadataDate} match the \protect\acro{PDF}
+%   \protect\pdfterm{CreationDate}}
+% \changes{v3.2}{2017/01/22}{Honor \string\pkgname{hyperref}'s
+%   \string\optname{pdfcreationdate} and \string\optname{pdfmoddate}
+%   options plus a new \string\optname{pdfmetadate} option.  Leonid
+%   Sinev requested this additional control and helped test the resulting
+%   \protect\pkgname{hyperxmp} code}
+%    \begin{macrocode}
+\newcommand*{\hyxmp@xmp@basic@schema}{%
+  \hyxmp@define@createdate
+%    \end{macrocode}
+% For the document's creation date, use the user-specified
+% |\@pdfcreationdate| if defined and non-empty.  Otherwise use our
+% fabricated |\hyxmp@createdate|.
+%    \begin{macrocode}
+  \@ifundefined{@pdfcreationdate}{%
+    \hyxmp@add@simple{xmp:CreateDate}{\hyxmp@createdate}%
+  }{%
+    \ifx\@pdfcreationdate\@empty
+      \hyxmp@add@simple{xmp:CreateDate}{\hyxmp@createdate}%
+    \else
+      \hyxmp@add@simple{xmp:CreateDate}{%
+        \expandafter\hyxmp@as@xmp@date\expandafter{\@pdfcreationdate}}%
+    \fi
+  }%
+%    \end{macrocode}
+% For the document's modification date, use the user-specified
+% |\@pdfmoddate| if defined and non-empty.  Otherwise use our
+% fabricated |\hyxmp@createdate|.
+%    \begin{macrocode}
+  \@ifundefined{@pdfmoddate}{%
+    \hyxmp@add@simple{xmp:ModifyDate}{\hyxmp@createdate}%
+  }{%
+    \ifx\@pdfmoddate\@empty
+      \hyxmp@add@simple{xmp:ModifyDate}{\hyxmp@createdate}%
+    \else
+      \hyxmp@add@simple{xmp:ModifyDate}{%
+        \expandafter\hyxmp@as@xmp@date\expandafter{\@pdfmoddate}}%
+    \fi
+  }%
+%    \end{macrocode}
+% For the document's metadata date, use the user-specified
+% |\@pdfmetadatetime| if defined and non-empty.  Otherwise use our
+% fabricated |\hyxmp@createdate|.
+%    \begin{macrocode}
+  \ifx\@pdfmetadatetime\@empty
+    \hyxmp@add@simple{xmp:MetadataDate}{\hyxmp@createdate}%
+  \else
+    \hyxmp@add@simple{xmp:MetadataDate}{\@pdfmetadatetime}%
+  \fi
+%    \end{macrocode}
+% Define the creation tool and the base \acro{URL}.
+%    \begin{macrocode}
+  \hyxmp@add@simple{xmp:CreatorTool}{\@pdfcreator}%
+  \hyxmp@add@simple{xmp:BaseURL}{\@baseurl}%
+}
+%    \end{macrocode}
+% \end{macro}
+%
+%
+% \subsubsection{The Photoshop schema}
+% \label{sec:photoshop}
+%
+% \begin{macro}{\hyxmp@photoshop@schema}
+% \changes{v2.0}{2012/08/26}{Simplified using
+%   \texttt{\string\string\string\hyxmp@add@simple}}
+% \begin{macro}{\hyxmp@photoshop@data}
+% Add properties defined by the Photoshop schema to the |\hyxmp@xml|
+% macro.  We currently support only the
+% \xmpprop{photoshop:AuthorsPosition} and
+% \xmpprop{photoshop:CaptionWriter} properties.
+%    \begin{macrocode}
+\gdef\hyxmp@photoshop@schema{%
+  \edef\hyxmp@photoshop@data{\@pdfauthortitle\@pdfcaptionwriter}%
+  \hyxmp@add@simple{photoshop:AuthorsPosition}{\@pdfauthortitle}%
+  \hyxmp@add@simple{photoshop:CaptionWriter}{\@pdfcaptionwriter}%
+}
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+%
+% \subsubsection{The PDF/A Identification schema}
+% \label{sec:pdfa-id}
+%
+% \begin{macro}{\hyxmp@pdfa@id@schema}
+% Add properties defined by the \acro{PDF/A} Identification
+% schema~\cite{PDFA2008:xmp-props} to the |\hyxmp@xml| macro.  These
+% properties identify a document as conforming to a particular
+% \acro{PDF/A} standard.  We default to \acro{PDF/A}-1b if any \acro{PDF/A}
+% compliance is detected but let the author override the ``1'' with
+% \optname{pdfapart} and the ``B'' with \optname{pdfaconformance}.
+% \changes{v2.4}{2013/12/21}{Added this macro}
+% \changes{v2.9}{2016/04/12}{Let the author specify the \protect\acro{PDF/A}
+%   part and conformance IDs, as requested by Leonid Sinev}
+%    \begin{macrocode}
+\newcommand*{\hyxmp@pdfa@id@schema}{%
+  \ifHy@pdfa
+    \hyxmp@add@simple{pdfaid:part}{\@pdfapart}%
+    \hyxmp@add@simple{pdfaid:conformance}{\@pdfaconformance}%
+  \fi
+}
+%    \end{macrocode}
+% \end{macro}
+%
+%
+% \subsubsection{The IPTC Photo Metadata schema}
+% \label{sec:photo-meta}
+%
+% \begin{macro}{\xmplinesep}
+% Lines in multiline fields are separated by |\xmplinesep| in the
+% generated \acro{XML}.  This defaults to an \acro{LF} (|^^J|) character
+% but written as an \acro{XML} character entity for consistency across
+% operating systems.
+% \changes{v2.2}{2012/12/07}{Added this macro}
+%    \begin{macrocode}
+\begingroup
+  \catcode`\&=12
+  \catcode`\#=12
+  \gdef\xmplinesep{&#xA;}
+\endgroup
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\hyxmp@list@to@lines}
+% Given a property~(|#1|) and a macro containing a comma-separated
+% list~(|#2|), replace commas with |\xmplinesep|.  Do nothing it the
+% list is empty.
+% \changes{v2.2}{2012/12/07}{Added this macro}
+%    \begin{macrocode}
+\newcommand*{\hyxmp@list@to@lines}[2]{%
+  \@ifnotmtargexp{#2}{%
+    \bgroup
+      \hyxmp@add@to@xml{%
+        \hyxmp@extra@indent______<#1>%
+      }%
+%    \end{macrocode}
+% \begin{macro}{\@elt@first}
+% The first element of the list is output as is.
+%    \begin{macrocode}
+      \def\@elt@first##1{%
+        \hyxmp@add@to@xml{##1}%
+        \let\@elt=\@elt@rest
+      }%
+%    \end{macrocode}
+% \begin{macro}{\@elt@rest}
+% The remaining elements of the list are output with a preceding line
+% separator (|\xmplinesep|).
+%    \begin{macrocode}
+      \def\@elt@rest##1{%
+        \hyxmp@add@to@xml{\xmplinesep##1}%
+      }%
+%    \end{macrocode}
+% \begin{macro}{\@elt}
+% Re-encode the text from \term{Unicode} if necessary.  Then redefine
+% |\@elt| to insert a line separator between terms.
+%    \begin{macrocode}
+      \let\@elt=\@elt@first
+      \hyxmp@xmlify{#2}%
+      \hyxmp@commas@to@list\hyxmp@list{\hyxmp@xmlified}%
+      \hyxmp@list
+      \hyxmp@add@to@xml{</#1>^^J}%
+    \egroup
+  }%
+}
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\hyxmp@iptc@schema}
+% Add properties defined by the \acro{IPTC} Photo Metadata
+% schema~\cite{IPTC2010:photo-meta} to the |\hyxmp@xml| macro.  We
+% currently support only the \xmpprop{Iptc4xmpCore:CreatorContactInfo}
+% property, although this is a structure containing multiple fields.
+% \changes{v2.2}{2012/12/07}{Added this macro}
+% \changes{v2.9}{2016/04/23}{Use \textsf{Iptc4xmpCore} instead of
+%   \textsf{Iptc4ContInfo} as the contact-information metadata prefix.
+%   Leonid Sinev reports that Acrobat's \acro{PDF/A} validator seems to
+%   prefer \textsf{Iptc4xmpCore}}
+% \changes{v4.0}{2019/03/09}{Moved the definition of
+%   \protect\cs{hyxmp@iptc@data} from here into
+%   \protect\cs{hyxmp@check@iptc@data}}
+% \changes{v4.0}{2019/03/16}{Renamed this macro to
+%   \protect\cs{hyxmp@iptc@schema} from
+%   \protect\cs{hyxmp@photometa@schema}}
+% \changes{v4.0}{2019/03/16}{Rewrote this macro entirely to correct
+%   the use of fields within a structure}
+%    \begin{macrocode}
+\gdef\hyxmp@iptc@schema{%
+%    \end{macrocode}
+% Because we currently support only
+% \xmpprop{Iptc4xmpCore:CreatorContactInfo} it suffices to check if we
+% have any relevant data.  If so, we instantiate a
+% \xmpprop{Iptc4xmpCore:ContactInfo} structure with all available
+% fields.
+%    \begin{macrocode}
+  \ifx\hyxmp@iptc@data\@empty
+  \else
+    \hyxmp@add@to@xml{%
+______<Iptc4xmpCore:CreatorContactInfo rdf:parseType="Resource">^^J%
+    }%
+%    \end{macrocode}
+% We locally redefine |\hyxmp@extra@indent| to increase the indentation
+% of the assignments to \xmpprop{Iptc4xmpCore:CreatorContactInfo}'s
+% fields.
+%    \begin{macrocode}
+    \bgroup
+      \edef\hyxmp@extra@indent{\hyxmp@extra@indent\space\space}%
+      \hyxmp@list@to@lines{Iptc4xmpCore:CiAdrExtadr}{\@pdfcontactaddress}%
+      \hyxmp@add@simple{Iptc4xmpCore:CiAdrCity}{\@pdfcontactcity}%
+      \hyxmp@add@simple{Iptc4xmpCore:CiAdrRegion}{\@pdfcontactregion}%
+      \hyxmp@add@simple{Iptc4xmpCore:CiAdrPcode}{\@pdfcontactpostcode}%
+      \hyxmp@add@simple{Iptc4xmpCore:CiAdrCtry}{\@pdfcontactcountry}%
+%    \end{macrocode}
+% \begin{macro}{\xmplinesep}
+% The \acro{IPTC} standard states that sets of telephone numbers, email
+% addresses, and \acro{URL}s for the contact person or institution,
+% ``[m]ay have to be separated by a comma in the user
+% interface''~\cite{IPTC2010:photo-meta}.  This is rather ambiguous:
+% Does the comma appear \emph{only} in the user interface or also in the
+% generated \acro{XML}\@?  Here we assume the latter interpretation and
+% temporarily redefine |\xmplinesep| as a comma and use
+% |\hyxmp@list@to@lines| to insert the data.  Unlike
+% |\hyxmp@add@simple|, this approach trims all spaces surrounding commas.
+%    \begin{macrocode}
+      \def\xmplinesep{,}%
+      \hyxmp@list@to@lines{Iptc4xmpCore:CiTelWork}{\@pdfcontactphone}%
+      \hyxmp@list@to@lines{Iptc4xmpCore:CiEmailWork}{\@pdfcontactemail}%
+      \hyxmp@list@to@lines{Iptc4xmpCore:CiUrlWork}{\@pdfcontacturl}%
+    \egroup
+    \hyxmp@add@to@xml{%
+______</Iptc4xmpCore:CreatorContactInfo>^^J%
+    }%
+  \fi
+}
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \subsubsection{The PRISM Basic Metadata schema}
+% \label{sec:prism-meta}
+%
+% \begin{macro}{\hyxmp@prism@schema}
+% \changes{v4.0}{2019/03/10}{Added this macro}
+% Add properties defined by the \acro{PRISM} Basic Metadata
+% schema~\cite{PRISM2012:basic-meta}.
+%    \begin{macrocode}
+\newcommand*{\hyxmp@prism@schema}{%
+  \ifx\hyxmp@prism@data\@empty
+  \else
+    \hyxmp@add@simple{prism:complianceProfile}{three}%
+  \fi
+  \hyxmp@add@simple@lang{prism:subtitle}{\@pdfsubtitle}%
+  \hyxmp@add@simple@lang{prism:publicationName}{\@pdfpublication}%
+  \hyxmp@add@simple{prism:aggregationType}{\@pdfpubtype}%
+  \hyxmp@add@simple@lang{prism:bookEdition}{\@pdfbookedition}%
+  \hyxmp@add@simple{prism:volume}{\@pdfvolumenum}%
+  \hyxmp@add@simple{prism:number}{\@pdfissuenum}%
+  \hyxmp@add@simple{prism:pageRange}{\@pdfpagerange}%
+  \hyxmp@add@simple{prism:isbn}{\@pdfisbn}%
+  \hyxmp@add@simple{prism:issn}{\@pdfissn}%
+  \hyxmp@add@simple{prism:eIssn}{\@pdfeissn}%
+  \hyxmp@add@simple{prism:doi}{\@pdfdoi}%
+  \hyxmp@add@simple{prism:url}{\@pdfurl}%
+  \hyxmp@add@simple{prism:byteCount}{\@pdfbytes}%
+  \hyxmp@add@simple{prism:pageCount}{\@pdfnumpages}%
+}
+%    \end{macrocode}
+% \end{macro}
+%
+% \subsubsection{XMP extension schemata}
+% \label{sec:extension-schemata}
+%
+% Not all of the schemata supported by \pkgname{hyperxmp} are predefined
+% by \acro{XMP}.  \acro{PDF/A} conversion would normally fail for
+% documents that employ ``custom'' schemata.  However, this problem can
+% be circumvented by declaring non-standard schemata in the \acro{XMP}
+% packet itself, following a technique described in a PDF Association
+% technical note~\cite{PDFA2008:ext-schemas}.  In this section, we
+% declare only those schemata we actually use.
+%
+% \begin{macro}{\hyxmp@check@iptc@data}
+% Define |\hyxmp@iptc@data| as the concatenation of all \acro{IPTC}
+% photo metadata supplied by the document.
+%    \begin{macrocode}
+\newcommand*{\hyxmp@check@iptc@data}{%
+%    \end{macrocode}
+% \begin{macro}{\hyxmp@iptc@data}
+%    \begin{macrocode}
+  \edef\hyxmp@iptc@data{%
+    \@pdfcontactaddress
+    \@pdfcontactcity
+    \@pdfcontactregion
+    \@pdfcontactpostcode
+    \@pdfcontactcountry
+    \@pdfcontactphone
+    \@pdfcontactemail
+    \@pdfcontacturl
+  }%
+}%
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\hyxmp@check@prism@data}
+% Define |\hyxmp@prism@data| as the concatenation of all \acro{PRISM}
+% metadata supplied by the document.
+%    \begin{macrocode}
+\newcommand*{\hyxmp@check@prism@data}{%
+%    \end{macrocode}
+% \begin{macro}{\hyxmp@prism@data}
+%    \begin{macrocode}
+  \edef\hyxmp@prism@data{%
+    \@pdfbookedition
+    \@pdfbytes
+    \@pdfdoi
+    \@pdfeissn
+    \@pdfisbn
+    \@pdfissn
+    \@pdfissuenum
+    \@pdfnumpages
+    \@pdfpagerange
+    \@pdfpublication
+    \@pdfpubtype
+    \@pdfsubtitle
+    \@pdfurl
+    \@pdfvolumenum
+  }%
+}%
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\hyxmp@begin@extension@decls}
+% Begin a block of \acro{XML} tags that indicates we're declaring one or
+% more extension schemata.
+%    \begin{macrocode}
+\newcommand*{\hyxmp@begin@extension@decls}{%
+  \hyxmp@add@to@xml{%
+______<pdfaExtension:schemas>^^J%
+________<rdf:Bag>^^J%
+  }%
+}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\hyxmp@end@extension@decls}
+% End the block of \acro{XML} tags begun by |\hyxmp@begin@extension@decls|.
+%    \begin{macrocode}
+\newcommand*{\hyxmp@end@extension@decls}{%
+  \hyxmp@add@to@xml{%
+________</rdf:Bag>^^J%
+______</pdfaExtension:schemas>^^J%
+  }%
+}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\hyxmp@begin@ext@decl}
+% Begin the declaration of a single extension schema.
+% |\hyxmp@begin@ext@decl| accepts the schema's name, prefix, and
+% namespace URI.
+% \changes{v4.0}{2019/03/15}{Added this macro}
+%    \begin{macrocode}
+\newcommand*{\hyxmp@begin@ext@decl}[3]{%
+  \hyxmp@add@to@xml{%
+__________<rdf:li rdf:parseType="Resource">^^J%
+____________<pdfaSchema:schema>#1</pdfaSchema:schema>^^J%
+____________<pdfaSchema:prefix>#2</pdfaSchema:prefix>^^J%
+____________<pdfaSchema:namespaceURI>#3</pdfaSchema:namespaceURI>^^J%
+____________<pdfaSchema:property>^^J%
+______________<rdf:Seq>^^J%
+  }%
+}%
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\hyxmp@end@ext@decl}
+% End the declaration of a single extension schema.
+% \changes{v4.0}{2019/03/15}{Added this macro}
+%    \begin{macrocode}
+\newcommand*{\hyxmp@end@ext@decl}{%
+  \hyxmp@add@to@xml{%
+______________</rdf:Seq>^^J%
+____________</pdfaSchema:property>^^J%
+__________</rdf:li>^^J%
+  }%
+}%
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\hyxmp@declare@property}
+% Declare a single extension-schema property.  |\hyxmp@declare@property|
+% takes as input an optional type (defaults to \xmpterm{Text}) and a
+% mandatory name, category, and description.
+% \changes{v4.0}{2019/03/15}{Added this macro}
+%    \begin{macrocode}
+\newcommand{\hyxmp@declare@property}[4][Text]{%
+  \hyxmp@add@to@xml{%
+________________<rdf:li rdf:parseType="Resource">^^J%
+__________________<pdfaProperty:name>#2</pdfaProperty:name>^^J%
+__________________<pdfaProperty:valueType>#1</pdfaProperty:valueType>^^J%
+__________________<pdfaProperty:category>#3</pdfaProperty:category>^^J%
+__________________<pdfaProperty:description>#4</pdfaProperty:description>^^J%
+________________</rdf:li>^^J%
+  }%
+}%
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\hyxmp@declare@field}
+% Declare a single field in a custom datatype required by an extension
+% schema.  |\hyxmp@declare@field| takes as input an optional type
+% (defaults to \xmpterm{Text}) and a mandatory name and description.
+% \changes{v4.0}{2019/03/16}{Replaced
+%   \protect\cs{hyxmp@declare@resource} with this macro}
+%    \begin{macrocode}
+\newcommand{\hyxmp@declare@field}[3][Text]{%
+  \hyxmp@add@to@xml{%
+______________________<rdf:li rdf:parseType="Resource">^^J%
+________________________<pdfaField:name>#2</pdfaField:name>^^J%
+________________________<pdfaField:valueType>#1</pdfaField:valueType>^^J%
+________________________<pdfaField:description>#3</pdfaField:description>^^J%
+______________________</rdf:li>^^J%
+  }%
+}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\hyxmp@mm@extensions}
+% Declare the \acro{XMP} Media Management schema.
+% \changes{v4.0}{2019/03/15}{Added this macro}
+%    \begin{macrocode}
+\newcommand*{\hyxmp@mm@extensions}{%
+  \hyxmp@begin@ext@decl
+      {XMP Media Management Schema}%
+      {xmpMM}%
+      {http://ns.adobe.com/xap/1.0/mm/}%
+  \hyxmp@declare@property
+      [URI]
+      {DocumentID}%
+      {internal}%
+      {UUID based identifier for all versions and renditions of a document}%
+  \hyxmp@declare@property
+      [URI]
+      {InstanceID}%
+      {internal}%
+      {UUID based identifier for specific incarnation of a document}%
+  \hyxmp@declare@property
+      {VersionID}%
+      {internal}%
+      {Document version identifier}%
+  \hyxmp@end@ext@decl
+}%
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\hyxmp@pdfa@id@extensions}
+% Declare the \acro{PDF/A} Identification schema~\cite{PDFA2008:xmp-props}.
+% \changes{v4.0}{2019/03/15}{Added this macro}
+%    \begin{macrocode}
+\newcommand*{\hyxmp@pdfa@id@extensions}{%
+  \hyxmp@begin@ext@decl
+      {PDF/A Identification Schema}%
+      {pdfaid}%
+      {http://www.aiim.org/pdfa/ns/id/}%
+  \hyxmp@declare@property
+      [Integer]%
+      {part}%
+      {internal}%
+      {Part of PDF/A standard}%
+  \hyxmp@declare@property
+      {conformance}%
+      {internal}%
+      {Conformance level of PDF/A standard}%
+  \hyxmp@end@ext@decl
+}%
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\hyxmp@iptc@extensions}
+% \changes{v2.2}{2012/12/13}{Added this macro to support
+%   \acro{PDF/A} generation}
+% \changes{v2.3}{2013/01/08}{Gave the
+%   \xmpprop{Iptc4xmpCore:CreatorContactInfo} fields a unique
+%   \xmpprop{pdfaType:prefix} to better support conversion of the
+%   document to \acro{PDF/A}}
+% \changes{v4.0}{2019/03/09}{Moved the header code from here into
+%   \protect\cs{hyxmp@begin@extension@decls} and the trailer code
+%   from here into \protect\cs{hyxmp@end@extension@decls}}
+% \changes{v4.0}{2019/03/16}{Rewrote to more closely honor the
+%   \acro{XMP} specification}
+% Because \acro{IPTC} metadata are not recognized by the \acro{PDF/A}
+% standard, \acro{PDF/A} conversion would normally fail for documents
+% that utilize \acro{IPTC} metadata.  Declaring the \acro{IPTC}
+% metadata we support enables the document to be converted to
+% \acro{PDF/A} format.
+%    \begin{macrocode}
+\newcommand*{\hyxmp@iptc@extensions}{%
+  \hyxmp@begin@ext@decl
+      {IPTC Core Schema}%
+      {Iptc4xmpCore}%
+      {http://iptc.org/std/Iptc4xmpCore/1.0/xmlns/}%
+  \hyxmp@declare@property
+      [ContactInfo]
+      {CreatorContactInfo}
+      {external}
+      {Document creator's contact information}
+%    \end{macrocode}
+% We can't call |\hyxmp@end@ext@decl| because we need first need to
+% define the \xmpprop{Iptc4xmpCore:ContactInfo} structure.
+%    \begin{macrocode}
+  \hyxmp@add@to@xml{%
+______________</rdf:Seq>^^J%
+____________</pdfaSchema:property>^^J%
+____________<pdfaSchema:valueType>^^J%
+______________<rdf:Seq>^^J%
+________________<rdf:li rdf:parseType="Resource">^^J%
+__________________<pdfaType:type>ContactInfo</pdfaType:type>^^J%
+__________________<pdfaType:namespaceURI>http://iptc.org/std/Iptc4xmpCore/1.0/xmlns/</pdfaType:namespaceURI>^^J%
+__________________<pdfaType:prefix>Iptc4xmpCore</pdfaType:prefix>^^J%
+__________________<pdfaType:description>%
+                   Basic set of information to get in contact with a person%
+                 </pdfaType:description>^^J%
+__________________<pdfaType:field>^^J%
+____________________<rdf:Seq>^^J%
+  }%
+  \hyxmp@declare@field
+      {CiAdrCity}%
+      {Contact information city}%
+  \hyxmp@declare@field
+      {CiAdrCtry}%
+      {Contact information country}%
+  \hyxmp@declare@field
+      {CiAdrExtadr}%
+      {Contact information address}%
+  \hyxmp@declare@field
+      {CiAdrPcode}%
+      {Contact information local postal code}%
+  \hyxmp@declare@field
+      {CiAdrRegion}%
+      {Contact information regional information such as state or province}%
+  \hyxmp@declare@field
+      {CiEmailWork}%
+      {Contact information email address(es)}%
+  \hyxmp@declare@field
+      {CiTelWork}%
+      {Contact information telephone number(s)}%
+  \hyxmp@declare@field
+      {CiUrlWork}%
+      {Contact information Web URL(s)}%
+  \hyxmp@add@to@xml{%
+____________________</rdf:Seq>^^J%
+__________________</pdfaType:field>^^J%
+________________</rdf:li>^^J%
+______________</rdf:Seq>^^J%
+____________</pdfaSchema:valueType>^^J%
+__________</rdf:li>^^J%
+  }%
+}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\hyxmp@prism@extensions}
+% \changes{v4.0}{2019/03/15}{Added this macro}
+% Because \acro{PRISM} metadata are not recognized by the \acro{PDF/A}
+% standard, \acro{PDF/A} conversion would normally fail for documents
+% that utilize \acro{PRISM} metadata.  Declaring the \acro{PRISM}
+% metadata we support enables the document to be converted to
+% \acro{PDF/A} format.
+%    \begin{macrocode}
+\newcommand*{\hyxmp@prism@extensions}{%
+  \hyxmp@begin@ext@decl
+      {PRISM Basic Metadata}%
+      {prism}%
+      {http://prismstandard.org/namespaces/basic/2.1/}%
+  \hyxmp@declare@property
+      {complianceProfile}%
+      {internal}%
+      {PRISM specification compliance profile to which this document adheres}%
+  \hyxmp@declare@property
+      {publicationName}%
+      {external}%
+      {Publication name}%
+  \hyxmp@declare@property
+      {aggregationType}%
+      {external}%
+      {Publication type}%
+  \hyxmp@declare@property
+      {bookEdition}%
+      {external}%
+      {Edition of the book in which the document was published}%
+  \hyxmp@declare@property
+      {volume}%
+      {external}%
+      {Publication volume number}%
+  \hyxmp@declare@property
+      {number}%
+      {external}%
+      {Publication issue number within a volume}%
+  \hyxmp@declare@property
+      {pageRange}%
+      {external}%
+      {Page range for the document within the print version of its publication}%
+  \hyxmp@declare@property
+      {issn}%
+      {external}%
+      {ISSN for the printed publication in which the document was published}%
+  \hyxmp@declare@property
+      {eIssn}%
+      {external}%
+      {ISSN for the electronic publication in which the document was published}%
+  \hyxmp@declare@property
+      {isbn}%
+      {external}%
+      {ISBN for the publication in which the document was published}%
+  \hyxmp@declare@property
+      {doi}%
+      {external}%
+      {Digital Object Identifier for the document}%
+  \hyxmp@declare@property
+      [URL]
+      {url}%
+      {external}%
+      {URL at which the document can be found}%
+  \hyxmp@declare@property
+      [Integer]
+      {byteCount}%
+      {internal}%
+      {Approximate file size in octets}%
+  \hyxmp@declare@property
+      [Integer]
+      {pageCount}%
+      {internal}%
+      {Number of pages in the print version of the document}%
+  \hyxmp@declare@property
+      {subtitle}%
+      {external}%
+      {Document's subtitle}%
+  \hyxmp@end@ext@decl
+}%
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\hyxmp@declare@extensions}
+% Declare all \acro{XMP} extension schemata.  We'll always have at least
+% one, the \acro{XMP} Media Management extensions, because we
+% automatically generate \xmpprop{xmpMM:DocumentID} and
+% \xmpprop{xmpMM:InstanceID}
+% values.
+%    \begin{macrocode}
+\newcommand*{\hyxmp@declare@extensions}{%
+  \hyxmp@begin@extension@decls
+%    \end{macrocode}
+% Declare the \acro{XMP} Media Management extensions (always present).
+%    \begin{macrocode}
+  \hyxmp@mm@extensions
+%    \end{macrocode}
+% Declare the \acro{PDF/A} Identification extensions, but only when
+% generating a \acro{PDF/A} document.
+%    \begin{macrocode}
+  \ifHy@pdfa
+    \hyxmp@mm@extensions
+  \fi
+%    \end{macrocode}
+% Conditionally declare \acro{IPTC} photo metadata extensions.
+%    \begin{macrocode}
+  \ifx\hyxmp@iptc@data\@empty
+  \else
+    \hyxmp@iptc@extensions
+  \fi
+%    \end{macrocode}
+% Conditionally declare \acro{PRISM} basic metadata extensions.
+%    \begin{macrocode}
+  \ifx\hyxmp@prism@data\@empty
+  \else
+    \hyxmp@prism@extensions
+  \fi
+%    \end{macrocode}
+%    \begin{macrocode}
+  \hyxmp@end@extension@decls
+}
+%    \end{macrocode}
+% \end{macro}
+%
+% \subsubsection{Combining schemata into an XMP packet}
+% \label{sec:combining-schemata}
+%
+% \begin{macro}{\hyxmp@bom}
+% Define a macro for the \term{Unicode} byte-order marker (\acro{BOM}).
+% \changes{v2.0}{2012/08/02}{Added by Heiko Oberdiek}
+%    \begin{macrocode}
+\begingroup
+  \ifhyxmp@unicodetex
+    \lccode`\!="FEFF %
+    \lowercase{%
+      \gdef\hyxmp@bom{!}
+    }%
+  \else
+    \catcode`\^^ef=12
+    \catcode`\^^bb=12
+    \catcode`\^^bf=12
+    \gdef\hyxmp@bom{^^ef^^bb^^bf}%
+  \fi
+\endgroup
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\hyxmp@construct@packet}
+% \changes{v1.1}{2006/05/21}{Explicitly set the category codes of
+%   characters \string\meta{EF}, \string\meta{BB}, and
+%   \string\meta{BF} to ``letter''.  Thanks to Daniel Sch\"omer for
+%   the bug report}
+% \changes{v2.0}{2012/08/02}{Modified by Heiko Oberdiek to use an
+%   appropriate \acro{BOM} representation via
+%   \texttt{\string\string\string\hyxmp@bom}}
+% \begin{macro}{\hyxmp@xml}
+% Successively add \acro{XML} data to |\hyxmp@xml| until we have
+% something we can insert into the document's \acro{PDF} catalog.
+%    \begin{macrocode}
+\def\hyxmp@construct@packet{%
+  \gdef\hyxmp@xml{}%
+  \hyxmp@add@to@xml{<?xpacket begin="\hyxmp@bom" %
+id="W5M0MpCehiHzreSzNTczkc9d"?>^^J%
+<x:xmpmeta xmlns:x="adobe:ns:meta/">^^J%
+__<rdf:RDF %
+xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns\hyxmp@hash">^^J%
+____<rdf:Description rdf:about=""^^J%
+%    \end{macrocode}
+% Specify every namespace we can potentially use, even the ones we end
+% up not actually using.
+%    \begin{macrocode}
+_____________________xmlns:pdf="http://ns.adobe.com/pdf/1.3/"^^J%
+_____________________xmlns:xmpRights="http://ns.adobe.com/xap/1.0/rights/"^^J%
+_____________________xmlns:dc="http://purl.org/dc/elements/1.1/"^^J%
+_____________________xmlns:photoshop="http://ns.adobe.com/photoshop/1.0/"^^J%
+_____________________xmlns:xmp="http://ns.adobe.com/xap/1.0/"^^J%
+_____________________xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/"^^J%
+_____________________xmlns:stEvt="http://ns.adobe.com/xap/1.0/sType/ResourceEvent\hyxmp@hash"^^J%
+_____________________xmlns:pdfaid="http://www.aiim.org/pdfa/ns/id/"^^J%
+_____________________xmlns:prism="http://prismstandard.org/namespaces/basic/2.1/"^^J%
+_____________________xmlns:Iptc4xmpCore="http://iptc.org/std/Iptc4xmpCore/1.0/xmlns/"^^J%
+_____________________xmlns:pdfaExtension="http://www.aiim.org/pdfa/ns/extension/"^^J%
+_____________________xmlns:pdfaSchema="http://www.aiim.org/pdfa/ns/schema\hyxmp@hash"^^J%
+_____________________xmlns:pdfaProperty="http://www.aiim.org/pdfa/ns/property\hyxmp@hash"^^J%
+_____________________xmlns:pdfaType="http://www.aiim.org/pdfa/ns/type\hyxmp@hash"^^J%
+_____________________xmlns:pdfaField="http://www.aiim.org/pdfa/ns/field\hyxmp@hash">^^J%
+  }%
+%    \end{macrocode}
+% Declare non-standard schemata.
+%    \begin{macrocode}
+  \hyxmp@check@iptc@data
+  \hyxmp@check@prism@data
+  \hyxmp@declare@extensions
+%    \end{macrocode}
+% Insert all the metadata we know how to insert.
+%    \begin{macrocode}
+  \hyxmp@pdf@schema
+  \hyxmp@xmpRights@schema
+  \hyxmp@dc@schema
+  \hyxmp@photoshop@schema
+  \hyxmp@xmp@basic@schema
+  \hyxmp@pdfa@id@schema
+  \hyxmp@mm@schema
+  \hyxmp@iptc@schema
+  \hyxmp@prism@schema
+  \hyxmp@add@to@xml{%
+____</rdf:Description>^^J%
+__</rdf:RDF>^^J%
+</x:xmpmeta>^^J%
+\hyxmp@padding
+<?xpacket end="w"?>^^J%
+  }%
+}
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+%
+% \subsection{Embedding the XMP packet}
+%
+% The \acro{PDF} specification says that ``a metadata stream may be
+% attached to a document through the \pdfterm{Metadata} entry in the
+% document catalogue''~\cite{Adobe2008:PDF} so that's what we do here.
+%
+% \begin{macro}{\hyxmp@embed@packet}
+% \begin{macro}{\hyxmp@driver}
+% Determine which \pkgname{hyperref} driver is in use and invoke the
+% appropriate embedding function.
+%    \begin{macrocode}
+\newcommand*{\hyxmp@embed@packet}{%
+  \hyxmp@construct@packet
+  \def\hyxmp@driver{hpdftex}%
+  \ifx\hyxmp@driver\Hy@driver
+    \hyxmp@embed@packet@pdftex
+  \else
+    \def\hyxmp@driver{hluatex}%
+    \ifx\hyxmp@driver\Hy@driver
+      \hyxmp@embed@packet@luatex
+    \else
+      \def\hyxmp@driver{hdvipdfm}%
+      \ifx\hyxmp@driver\Hy@driver
+        \hyxmp@embed@packet@dvipdfm
+      \else
+        \def\hyxmp@driver{hxetex}%
+        \ifx\hyxmp@driver\Hy@driver
+          \hyxmp@embed@packet@xetex
+        \else
+          \@ifundefined{pdfmark}{%
+            \PackageWarningNoLine{hyperxmp}{%
+              Unrecognized hyperref driver `\Hy@driver'.\MessageBreak
+              \jobname.tex's XMP metadata will *not* be\MessageBreak
+              embedded in the resulting file}%
+          }{%
+            \hyxmp@embed@packet@pdfmark
+          }%
+        \fi
+      \fi
+    \fi
+  \fi
+}
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \subsubsection{Embedding using \pdfTeX}
+%
+% Up to version~0.85, \LuaTeX\ supported the \pdfTeX\ primitives, and
+% \pkgname{hyperref} didn't distinguish the two backends.  However, from
+% \pkgname{hyperxmp}'s perspective there is one key difference: the
+% effect of |\pdfcompresslevel| is local to a group in \pdfTeX\ but is
+% global in \LuaTeX\@.
+%
+% The \acro{PDF} object representing the \acro{XMP} packet is supposed
+% to include an uncompressed stream so it can be read by
+% non-\acro{PDF}-aware tools.  However, we don't want to unnecessarily
+% uncompress \emph{every} \acro{PDF} stream.  The solution, provided by
+% Hans Hagen on the |luatex| mailing list (thread:
+% \href{http://tug.org/pipermail/luatex/2016-July/006077.html}{``Leaving
+%   a single \acro{PDF} object uncompressed''}, 6\,\textsc{Jul}\,2016),
+% is to provide the |uncompressed| flag to |\pdfobj|.  Our definition of
+% |\hyxmp@embed@packet@pdftex| uses the \pkgname{ifluatex} package to
+% distinguish the \pdfTeX\ case from the pre-0.85 \LuaTeX\ case.
+%
+%    \begin{macrocode}
+\RequirePackage{ifluatex}
+%    \end{macrocode}
+%
+% \begin{macro}{\hyxmp@embed@packet@pdftex}
+% Embed the \acro{XMP} packet using \pdfTeX\ primitives, which are
+% supported by both \pdfTeX\ and pre-0.85 \LuaTeX.  The only difference
+% is that in the former case we locally specify |\pdfcompresslevel=0| to
+% leave the \acro{PDF} object uncompressed while in the latter case we
+% pass the |uncompressed| flag to |\pdfobj| to achieve the same effect.
+% \changes{v3.1}{2016/07/06}{Leave the \protect\acro{XMP} packet---and
+%   only the \protect\acro{XMP} packet---uncompressed in both
+%   \protect\pdfTeX\ and pre-0.85 \protect\LuaTeX}
+%    \begin{macrocode}
+\newcommand*{\hyxmp@embed@packet@pdftex}{%
+  \bgroup
+    \ifluatex
+    \else
+      \pdfcompresslevel=0
+    \fi
+    \immediate\pdfobj \ifluatex uncompressed\fi stream attr {%
+      /Type /Metadata
+      /Subtype /XML
+    }{\hyxmp@xml}%
+    \pdfcatalog {/Metadata \the\pdflastobj\space 0 R}%
+  \egroup
+}
+%    \end{macrocode}
+% \end{macro}
+%
+% \subsubsection{Embedding using \LuaTeX~0.85+}
+%
+% \begin{macro}{\hyxmp@embed@packet@luatex}
+% Embed the \acro{XMP} packet using \LuaTeX~0.85+ primitives.
+% \changes{v3.0}{2016/07/02}{Added this macro}
+% \changes{v3.1}{2016/07/06}{Updated to use
+%   \protect\texttt{\string\string\string\pdfextension\ obj uncompressed}
+%   as suggested by Hans Hagen}
+%    \begin{macrocode}
+\newcommand*{\hyxmp@embed@packet@luatex}{%
+  \immediate\pdfextension obj uncompressed stream attr {%
+    /Type /Metadata
+    /Subtype /XML
+  }{\hyxmp@xml}%
+  \pdfextension catalog {/Metadata \the\numexpr\pdffeedback lastobj\relax\space 0 R}%
+}
+%    \end{macrocode}
+% \end{macro}
+%
+% \subsubsection{Embedding using any \texttt{pdfmark}-based backend}
+%
+% \begin{macro}{\hyxmp@embed@packet@pdfmark}
+% Embed the \acro{XMP} packet using \pkgname{hyperref}'s |\pdfmark|
+% command.  I believe |\pdfmark| is used by the \optname{dvipdf},
+% \optname{dvipsone}, \optname{dvips}, \optname{dviwindo},
+% \optname{nativepdf}, \optname{pdfmark}, \optname{ps2pdf},
+% \optname{textures}, and \optname{vtexpdfmark} options to
+% \pkgname{hyperref}, but I've tested only a few of those.
+%    \begin{macrocode}
+\newcommand*{\hyxmp@embed@packet@pdfmark}{%
+  \pdfmark{%
+    pdfmark=/NamespacePush
+  }%
+  \pdfmark{%
+    pdfmark=/OBJ,
+    Raw={/_objdef \string{hyxmp@Metadata\string} /type /stream}%
+  }%
+  \pdfmark{%
+    pdfmark=/PUT,
+    Raw={\string{hyxmp@Metadata\string}
+      2 dict begin
+        /Type /Metadata def
+        /Subtype /XML def
+        currentdict
+      end
+    }%
+  }%
+  \pdfmark{%
+    pdfmark=/PUT,
+    Raw={\string{hyxmp@Metadata\string} (\hyxmp@xml)}%
+  }%
+  \pdfmark{%
+    pdfmark=/Metadata,
+    Raw={\string{Catalog\string} \string{hyxmp@Metadata\string}}%
+  }%
+  \pdfmark{%
+    pdfmark=/NamespacePop
+  }%
+}
+%    \end{macrocode}
+% \end{macro}
+%
+% \subsubsection{Embedding using \texttt{dvipdfm}}
+%
+% \begin{macro}{\hyxmp@embed@packet@dvipdfm}
+% Embed the \acro{XMP} packet using \cmdname{dvipdfm}-specific
+% |\special| commands.  Note that \cmdname{dvipdfm} rather irritatingly
+% requires us to count the number of characters in the |\hyxmp@xml|
+% stream ourselves.
+%    \begin{macrocode}
+\newcommand*{\hyxmp@embed@packet@dvipdfm}{%
+  \hyxmp@string@len{\hyxmp@xml}%
+  \special{pdf: object @hyxmp@Metadata
+    <<
+      /Type /Metadata
+      /Subtype /XML
+      /Length \the\@tempcnta
+    >>
+    stream^^J\hyxmp@xml endstream%
+  }%
+  \special{pdf: docview
+    <<
+      /Metadata @hyxmp@Metadata
+    >>
+  }%
+}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\hyxmp@string@len}
+% Set |\@tempcnta| to the number of characters in a given string~(|#1|).
+% The approach is first to tally the number of space characters then to
+% tally the number of non-space characters.  While this is rather
+% sloppy I haven't found a better way to achieve the same effect,
+% especially given that all of the characters in |#1| have already been
+% assigned their category codes.
+%    \begin{macrocode}
+\newcommand*{\hyxmp@string@len}[1]{%
+  \@tempcnta=0
+  \expandafter\hyxmp@count@spaces#1 {} %
+  \expandafter\hyxmp@count@non@spaces#1{}%
+}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\hyxmp@count@spaces}
+% Count the number of spaces in a given string.  We rely on the built-in
+% pattern matching of \tex's |\def| primitive to pry one word at a time
+% off the head of the input string.
+%    \begin{macrocode}
+\def\hyxmp@count@spaces#1 {%
+  \def\hyxmp@one@token{#1}%
+  \ifx\hyxmp@one@token\@empty
+    \advance\@tempcnta by -1
+  \else
+    \advance\@tempcnta by 1
+    \expandafter\hyxmp@count@spaces
+  \fi
+}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\hyxmp@count@non@spaces}
+% Count the number of non-spaces in a given string.  Ideally, we'd count
+% both spaces and non-spaces but \tex\ won't bind |#1| to a space
+% character (category code~10).  Hence, in each iteration, |#1| is bound
+% to the next non-space character only.
+%    \begin{macrocode}
+\newcommand*{\hyxmp@count@non@spaces}[1]{%
+  \def\hyxmp@one@token{#1}%
+  \ifx\hyxmp@one@token\@empty
+  \else
+    \advance\@tempcnta by 1
+    \expandafter\hyxmp@count@non@spaces
+  \fi
+}
+%    \end{macrocode}
+% \end{macro}
+%
+% \subsubsection{Embedding using \XeTeX}
+%
+% \begin{macro}{\hyxmp@embed@packet@xetex}
+% Embed the \acro{XMP} packet using \cmdname{xdvipdfmx}-specific
+% |\special| commands.  I don't know how to tell \cmdname{xdvipdfmx}
+% always to leave the \pdfterm{Metadata} stream uncompressed, so the
+% \acro{XMP} metadata is likely to be missed by non-\acro{PDF}-aware
+% \acro{XMP} viewers.
+%    \begin{macrocode}
+\newcommand*{\hyxmp@embed@packet@xetex}{%
+  \special{pdf:stream @hyxmp@Metadata (\hyxmp@xml)
+    <<
+      /Type /Metadata
+      /Subtype /XML
+    >>
+  }%
+  \special{pdf:put @catalog
+    <<
+      /Metadata @hyxmp@Metadata
+    >>
+  }%
+}
+%    \end{macrocode}
+% \end{macro}
+%
+%
+% \subsection{Final clean-up}
+% \label{sec:clean-up}
+%
+% Having saved the category code of
+% ``\,{\fontencoding{T1}\selectfont\textquotedbl}\,'' at the start of
+% the package code (Section~\ref{sec:initial-prep}), we now restore that
+% character's original category code.
+%
+%    \begin{macrocode}
+\catcode`\"=\hyxmp@dq@code
+%    \end{macrocode}
+%
+% \Finale
+\endinput
-- 
cgit v1.2.3

