Once metadata has been created, inevitably, some of the information it contains will change over time. If the information is specific to one ArcGIS item, you can edit its metadata to change the information. However, if the information that changed is included in the metadata for many ArcGIS items, the process of manually editing metadata for all affected items is tedious. Fortunately, different techniques are available to update many items' metadata at once.
Metadata is considered to be internal to an ArcGIS item, regardless of how an ArcGIS item stores this information. When you ask an ArcGIS item to provide its metadata, it will provide this information as an XML document. There are two general approaches for updating the metadata stored in the provided XML document. The most common method for changing an XML file's content is to use an XSLT stylesheet. XML files can also be modified programmatically. In both cases, you must first save the XML document to an XML file. Then, you can modify the XML file's content either by processing it with an XSLT stylesheet or by programmatically modifying its content, such as with a Python script.
Create an XSLT stylesheet to update metadata
You can use a custom XSLT stylesheet to update an item's metadata content. A model like the one below can be used to first process an item's metadata using the XSLT stylesheet of your choice with the XSLT Transformation tool. The result of this process is saved to an XML file. Then, the model saves the updated XML document back to the original ArcGIS item as its metadata using the Metadata Importer tool.
Learn more about processing an item's metadata using XSLT stylesheets
There are many resources available on the Internet that can help you learn how to create custom XSLT stylesheets. However, the examples below will help you get started. They illustrate how to change an organization's contact information.
Suppose the original metadata included a metadata contact as shown below, where the following is true:
- The individual name is Reception.
- The organization name is Esri Learning Center.
- The street address is 380 New York St.
- The city is Redlands.
- The state is California, CA.
- The ZIP Code is 92373.
- The country is the United States of America, US.
- The email address is info@esri.com.
- The phone number is 909-793-2853.
- The fax number is 909-793-4801.
- The role specified for this contact is publisher, 010.
An excerpt of a metadata XML document where the organization's contact information must be updated.
<?xml version="1.0" encoding="UTF-8"?>
<metadata>
<mdContact>
<rpIndName>Reception</rpIndName>
<rpOrgName>Esri Learning Center</rpOrgName>
<rpCntInfo>
<cntAddress>
<delPoint>380 New York St.</delPoint>
<city>Redlands</city>
<adminArea>CA</adminArea>
<postCode>92373</postCode>
<country>US</country>
<eMailAdd>info@esri.com</eMailAdd>
</cntAddress>
<cntPhone>
<voiceNum>909-793-2853</voiceNum>
<faxNum>909-793-4801</faxNum>
</cntPhone>
</rpCntInfo>
<role>
<RoleCd value="010"/>
</role>
</mdContact>
...
</metadata>
In this scenario, this contact information must be edited as follows:
- Remove the individual name from the contact information.
- Change the ZIP Code to 92373-8100.
- Change the email address to LearnGIS@esri.com.
- Change the phone number to 888-377-4575 x.1-3204.
- Add the location of a web page where you can find information on the Internet, http://www.esri.com/training.
- Add information about when you can contact the organization, 8:00am to 5:00pm Pacific Time.
The rest of the contact information will stay the same.
The following XSLT stylesheet will perform these edits. The individual name metadata element will be removed. The entire address, with all its individual metadata elements, is updated at once. The phone number is updated separately from the rest of the phone information. To add the web page and hours of availability, all other existing contact information must be copied so it isn't lost before the new information is added.
An XSLT stylesheet that edits contact information for one organization and copies all other metadata content.
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" omit-xml-declaration="no" />
<!-- process the metadata using the templates below -->
<xsl:template match="/">
<xsl:apply-templates select="node() | @*" />
</xsl:template>
<!-- copy all metadata conent -->
<xsl:template match="node() | @*" priority="0">
<xsl:copy>
<xsl:apply-templates select="node() | @*" />
</xsl:copy>
</xsl:template>
<!-- all metadata XSLT stylesheets used to update metadata should be identical to this example up to this point -->
<!-- add the templates you'll use to update the metadata below -->
<!-- remove the individual name from the contact information for the organization name Esri Learning Center -->
<xsl:template match="rpIndName[../rpOrgName = 'Esri Learning Center']" priority="1" >
</xsl:template>
<!-- edit the address for any contact with the organization name Esri Learning Center -->
<xsl:variable name="newAddress" >
<cntAddress>
<delPoint>380 New York St.</delPoint>
<city>Redlands</city>
<adminArea>CA</adminArea>
<postCode>92373-8100</postCode>
<country>US</country>
<eMailAdd>LearnGIS@esri.com</eMailAdd>
</cntAddress>
</xsl:variable>
<xsl:template match="cntAddress[../../rpOrgName = 'Esri Learning Center']" priority="1" >
<xsl:copy-of select="$newAddress" />
</xsl:template>
<!-- edit all contacts with the organization name Esri Learning Center to have a new phone number -->
<xsl:variable name="newPhone">888-377-4575 x.1-3204</xsl:variable>
<xsl:template match="voiceNum[../../../rpOrgName = 'Esri Learning Center']" priority="1" >
<voiceNum><xsl:value-of select="$newPhone" /></voiceNum>
</xsl:template>
<!-- add hours of availability for the organization name Esri Learning Center -->
<xsl:template match="rpCntInfo[../rpOrgName = 'Esri Learning Center']" priority="1" >
<xsl:copy>
<xsl:apply-templates select="node() | @*" />
<cntOnlineRes>
<linkage>http://www.esri.com/training</linkage>
</cntOnlineRes>
<cntHours>8:00am to 5:00pm Pacific Time</cntHours>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
When this XSLT stylesheet is used to edit the example metadata shown above using the XSLT Transformation tool, the output XML file below will be created as output. Use the Metadata Importer tool to save these changes with the original ArcGIS item.
An excerpt of the updated metadata produced by the above XSLT stylesheet.
<?xml version="1.0" encoding="UTF-8"?>
<metadata>
<mdContact>
<rpOrgName>Esri Learning Center</rpOrgName>
<rpCntInfo>
<cntAddress>
<delPoint>380 New York St.</delPoint>
<city>Redlands</city>
<adminArea>CA</adminArea>
<postCode>92373-8100</postCode>
<country>US</country>
<eMailAdd>LearnGIS@esri.com</eMailAdd>
</cntAddress>
<cntPhone>
<voiceNum>888-377-4575 x.1-3204</voiceNum>
<faxNum>909-793-4801</faxNum>
</cntPhone>
<cntOnlineRes>
<linkage>http://www.esri.com/training</linkage>
</cntOnlineRes>
<cntHours>8:00am to 5:00pm Pacific Time</cntHours>
</rpCntInfo>
<role>
<RoleCd value="010"/>
</role>
</mdContact>
...
</metadata>
Several XSLT stylesheets are provided with ArcGIS Desktop to support the metadata geoprocessing models in the Conversion toolbox, in the <ArcGIS Installation Location>\Metadata\Stylesheets\gpTools folder. Use these as examples.
When creating your own stylesheets, it helps to understand the XML format you're working with. An XML DTD describing the ArcGIS metadata XML format is provided in the <ArcGIS Installation Location>\Metadata\Translator\Rules folder.
Update metadata with Python scripts
Another approach is to use a Python script to update an item's metadata content. The Python script must execute the same geoprocessing tools as the model described above that processes metadata using an XSLT stylesheet. The XSLT Transformation tool is used first to save a copy of the item's metadata to an XML file using the exact copy of.xslt stylesheet provided with ArcGIS Desktop. The resulting XML file can be modified with a Python script. Then, the updated XML document must be saved back to the original ArcGIS item as its metadata using the Metadata Importer tool.
The Python script below changes the text in an existing Purpose element, if one exists, and adds a new Credits element. The XML document is modified using the Python ElementTree API, which is documented in the standard Python library. Other APIs may be available from other Python packages to modify XML files; you may choose to use these instead.
A Python script that updates the Purpose element and adds a new Credits element to an item's metadata.
# batch update metadata for datasets in a folder
import os, sys
import arcpy
import xml.etree.ElementTree as ET
# arcpy environments
arcpy.env.overwriteOutput = "True"
# Script arguments...
Source_Metadata = arcpy.GetParameter(0)
# Local variables
# new purpose text
newPurpose = "This is new text for an existing Purpose metadata element."
newCredits = "This is text for a new Credits metadata element."
# install location
dir = arcpy.GetInstallInfo("desktop")["InstallDir"]
# stylesheet to use
copy_xslt = r"{0}".format(os.path.join(dir,"Metadata\Stylesheets\gpTools\exact copy of.xslt"))
arcpy.AddMessage("XSLT: {0}".format(copy_xslt))
def update_metadata(root):
num_elements = 0
# modify purpose element's text
# there is only supposed to be one purpose element in metadata
# replace purpose element text if element exists
# if element doesn't exist, do nothing
purposeEls = root.findall(".//idPurp")
for element in purposeEls:
if element.text is not None:
element.text = newPurpose
num_elements += 1
# add credits element to dataIdInfo parent, if the parent exists
# ISO allows many dataIdInfo groups; ArcGIS generally supports only one, get the 1st
# ISO allows many idCredit elements: 1st on Item Description page, all on Resource Details page
# always append new idCredit element to 1st dataIdInfo with appropriate text
# existing idCredit elements remain in place
dataIdInfoEls = root.findall("./dataIdInfo[1]")
for element in dataIdInfoEls:
if element:
newCreditEl = ET.SubElement(element,"idCredit")
newCreditEl.text = newCredits
num_elements += 1
return num_elements
for item in Source_Metadata:
arcpy.AddMessage("Item: {0}".format(item))
# temporary XML file
xmlfile = arcpy.CreateScratchName(".xml",workspace=arcpy.env.scratchFolder)
#arcpy.AddMessage("Temporary XML file: {0}".format(xmlfile))
# export xml
arcpy.XSLTransform_conversion(item, copy_xslt, xmlfile, "")
# read in XML
tree = ET.parse(xmlfile)
root = tree.getroot()
changes = update_metadata(root)
#arcpy.AddMessage("number of elements updated: {0}".format(changes))
if changes > 0:
# save modifications to XML
#arcpy.AddMessage("Saving changes to temporary file...")
tree.write(xmlfile)
# import result back into metadata
arcpy.AddMessage("Saving updated metadata with the item...")
arcpy.MetadataImporter_conversion(xmlfile, item)
else:
arcpy.AddMessage("No changes to save")
arcpy.AddMessage('Finished updating metadata for all source metadata items')