Formal metadata: information and software
Formal metadata information and software
C:\Tcl
C:\USGS.
cd C:\USGS\tools\bin copy mq26.dll C:\Tcl\lib mkdir C:\Tcl\lib\mq copy pkgIndex.tcl C:\Tcl\lib\mq
C:\> tclsh % puts "Hello, World!" Hello, World! % expr 2 + 2 4 % expr 355.0 / 113 3.14159292035 % exit(To quit the Tcl interpreter, enter "
exit"; "quit" doesn't do it.)
[like this] gets executed and is replaced by its
result. So in the example puts "Have some [expr 355.0 / 113]",
the text between the braces is replaced by "3.14159292035", and that
statement prints Have some 3.14159292035. See the Tcl
Tutorial at http://www.tcl.tk/man/tcl8.5/tutorial/tcltutorial.html;
there are a number of good books on Tcl as well.
metadata m -parse c:/USGS/tools/doc/metadata/mp.metReturns 1 if mq managed to find and read the metadata record, 0 otherwise. So you can write
if {[metadata m -parse c:/USGS/tools/doc/metadata/mp.xml]} {
# do some things with this record
}
Notice that in this case I'm reading the XML version of the file; like
mp, mq can read indented text or XML or SGML.
Notice also that we use forward slashes for directory separators, not
backslashes (use / instead of \).
If this works, we use the variable m to work with the metadata.
For example, to find the Identification_Information, we write
$m find_first Identification_InformationWhat we get from this is the address of the Identification_Information. Normally we need to store that address in a variable:
set p [$m find_first Identification_Information]We don't manipulate that address directly, but we pass it to other mq functions, for example, to find an element within another:
set q [$m find_in $p Cross_Reference]This will return the address of the first Cross_Reference element within the element
p; the address of the Cross_Reference element is stored in
the variable q.
set p [$m find_first Identification_Information]
if {$p} {
set q [$m find_in $p Cross_Reference]
}
Since the Tcl set command returns the value you're setting, you can use
it as a test in an if statement. This produces a more compact form:
if {[set p [$m find_first Identification_Information]]} {
if {[set q [$m find_in $p Cross_Reference]]} {
# do something with the cross reference that is now in q
}
}
To get one of the element's values:
if {[set p [$m find_first Access_Constraints]]} {
# Get the text of Access_Constraints, store in variable t
set t [$m value_of $p]
# print the value
puts "$t"
}
To set an element's value:
if {[set p [$m find_first Access_Constraints]]} {
# Set the text of Access_Constraints to "None"
$m value_set $p "None"
}
If you've made changes and you want to keep them, write the file. If you
don't specify a file name, mq overwrites the original file. You can save
the data in a format different from the one you read (so mq can be used to
convert from indented text to XML and back again).
$m write $m write my_copy.xmlWhen you're working with many files, don't keep track of them all at once unless you really have to; instead,
forget about each one as soon as
you're done getting information from it:
$m forgetThere are many more operations you can carry out on metadata. See mq's reference manual for a complete list.
# Open the metadata record
metadata m -parse C:/USGS/tools/doc/metadata/mp.met
# Find the Citation
if {[set p [$m find_first Citation]]} {
# Find the title within the Citation.
if {[set q [$m find_in $p Title]]} {
# Get the value of the title and print it out.
set t [$m value_of $q]
puts "$t"
} \
else {
# If no Title exists, complain.
puts "This record has no title."
}
}
# When done, forget about this record.
$m forget
# Open the metadata record
metadata m -parse C:/data/catfish.xml
# Find the Keywords section. There's only one of these.
if {[set p [$m find_first Keywords]]} {
# Look for Place within Keywords. This can be repeated.
if {[set q [$m find_in $p Place]]} {
# If there is one Place, there may be more of them.
while {$q} {
# Find and print the Place_Keyword_Thesaurus, if any
if {[set r [$m find_in $q Place_Keyword_Thesaurus]]} {
# Get the value and print it out.
set t [$m value_of $r]
puts "Place terms from thesaurus $t"
} \
else {
puts "No Place_Keyword_Thesaurus within this Place!"
}
# Look for Place_Keywords within this Place. Repeats.
set u [$m find_in $q Place_Keyword]
while {$u} {
# Get the value and print it out.
set t [$m value_of $u]
puts " $t"
# Find the next Place_Keyword.
set u [$m find_next $u]
}
# Find the next Place section
set q [$m find_next $q]
}
}
}
# When done, forget about this record.
$m forget
proc process_directory {long_name short_name} {
recurse $long_name
}
proc process_file {long_name short_name} {
if {[string compare [file extension $short_name] .met] == 0} {
# operations on each metadata record go here
}
}
proc recurse {dir} {
global root
foreach long_name [lsort [glob [file join $dir *]]] {
scan $long_name "$root/%s" short_name
if {[file isdirectory $long_name]} {
process_directory $long_name $short_name
} \
else {
process_file $long_name $short_name
}
}
}
set root [pwd]
set short_name .
recurse $root
Peter N. Schweitzer
Mail Stop 954, National Center
U.S. Geological Survey
Reston, VA 20192
Tel: (703) 648-6533
FAX: (703) 648-6252
Email: pschweitzer@usgs.gov