source: metadata/trunk/toolkit/src/main/resources/toolkit/xsd/cmd-component.xsd @ 6908

Last change on this file since 6908 was 6908, checked in by Menzo Windhouwer, 9 years ago

M toolkit/src/main/resources/toolkit/xsd/cmd-component.xsd
M toolkit/src/main/resources/toolkit/sch/cmd-component-best-practices.sch

  • moved a_nest Schematron rule to best practices

M toolkit/src/main/resources/toolkit/upgrade/cmd-record-1_1-to-1_2.xsl

  • added TODO
  • Property svn:executable set to *
  • Property svn:keywords set to
    Rev
    Date
  • Property svn:mergeinfo set to (toggle deleted branches)
    /ComponentRegistry/branches/ComponentRegistry-1.12.0/ComponentRegistry/src/main/binding/general-component-schema.xsd2071-2124
    /ComponentRegistry/branches/ComponentRegistry-1.13.0-olha/ComponentRegistry/src/main/binding/components/general-component-schema.xsd2143-2514
    /ComponentRegistry/branches/ComponentRegistry-schematron/ComponentRegistry/src/main/binding/general-component-schema.xsd1751-1797
    /ComponentRegistry/tags/ComponentRegistry-1.8.1/ComponentRegistry/src/main/binding/general-component-schema.xsd1420-1453
    /ComponentRegistry/tags/ComponentRegistry-1.9.1/ComponentRegistry/src/main/binding/general-component-schema.xsd1565
    /ComponentRegistry/trunk/ComponentRegistry/src/main/binding/components/general-component-schema.xsd2143-2395
    /ComponentRegistry/trunk/ComponentRegistry/src/main/binding/general-component-schema.xsd17-1476
    /ComponentRegistry/trunk/ComponentRegistry/src/test/resources/clarin_catalog/general-component-schema.xsd3885-3892
File size: 24.8 KB
Line 
1<?xml version="1.0" encoding="UTF-8"?>
2<!--
3    $Revision: 6908 $
4    $Date: 2016-01-14 13:05:14 +0000 (Thu, 14 Jan 2016) $
5-->
6
7<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:sch="http://purl.oclc.org/dsdl/schematron"
8    xmlns:vc="http://www.w3.org/2007/XMLSchema-versioning" vc:minVersion="1.0" vc:maxVersion="1.1">
9
10    <xs:import namespace="http://www.w3.org/XML/1998/namespace"
11        schemaLocation="http://www.w3.org/2005/08/xml.xsd"/>
12
13    <!-- root element -->
14    <xs:element name="ComponentSpec">
15        <xs:annotation>
16            <xs:appinfo>
17                <sch:pattern id="h_succ">
18                    <sch:title>Check successor</sch:title>
19                    <sch:rule context="Header/Successor">
20                        <sch:assert test="../Status='deprecated'">There can only be a successor component/profile if the status of this component/profile is deprecated!</sch:assert>
21                    </sch:rule>
22                </sch:pattern>
23                <sch:pattern id="r_card">
24                    <sch:title>Cardinality root component</sch:title>
25                    <sch:rule context="ComponentSpec/Component">
26                        <sch:assert test="empty(@CardinalityMin) or @CardinalityMin='1'">The minimum cardinality of the root component should be 1!</sch:assert>
27                        <sch:assert test="empty(@CardinalityMax) or @CardinalityMax='1'">The maximum cardinality of the root component should be 1!</sch:assert>
28                    </sch:rule>
29                </sch:pattern>
30            </xs:appinfo>
31        </xs:annotation>
32        <xs:complexType>
33            <xs:sequence>
34                <xs:element name="Header">
35                    <xs:complexType>
36                        <xs:sequence>
37                            <xs:element name="ID" type="xs:anyURI" minOccurs="0" maxOccurs="1"/>
38                            <xs:element name="Name" type="xs:string" minOccurs="1" maxOccurs="1"/>
39                            <xs:element name="Description" type="xs:string" minOccurs="0" maxOccurs="1"/>
40                            <!-- status information -->
41                            <xs:element name="Status" minOccurs="1" maxOccurs="1">
42                                <xs:simpleType>
43                                    <xs:restriction base="xs:string">
44                                        <xs:enumeration value="development"/>
45                                        <xs:enumeration value="production"/>
46                                        <xs:enumeration value="deprecated"/>
47                                    </xs:restriction>
48                                </xs:simpleType>
49                            </xs:element>
50                            <xs:element name="StatusComment" type="xs:string" minOccurs="0" maxOccurs="1"/>
51                            <xs:element name="Successor" type="xs:anyURI" minOccurs="0" maxOccurs="1"/>
52                        </xs:sequence>
53                    </xs:complexType>
54                </xs:element>
55                <xs:element name="Component" type="Component_type">
56                    <xs:annotation>
57                        <xs:documentation>At the root level there should always be a Component.</xs:documentation>
58                    </xs:annotation>
59                </xs:element>
60            </xs:sequence>
61            <xs:attribute name="isProfile" type="xs:boolean" use="required"/>
62        </xs:complexType>
63    </xs:element>
64
65    <!-- recursive construction: A component can contain elements and/or other components  -->
66    <xs:group name="group">
67        <xs:annotation>
68            <xs:appinfo>
69                <sch:pattern id="c_sibs">
70                    <sch:title>Check siblings</sch:title>
71                    <sch:rule context="Component|Element">
72                        <sch:assert test="empty(preceding-sibling::*[@name=current()/@name])">Sibling components or elements should all have a different name. Found multiple components or elements named '<sch:value-of select="@name"/>'!</sch:assert>
73                    </sch:rule>
74                </sch:pattern>
75                <sch:pattern id="c_csibs">
76                    <sch:title>Check component siblings</sch:title>
77                    <sch:rule context="Component">
78                        <sch:assert test="empty(preceding-sibling::Component[@ComponentId=current()/@ComponentId])">Sibling components should all be different. Found multiple components with id '<sch:value-of select="@ComponentId"/>'!</sch:assert>
79                    </sch:rule>
80                </sch:pattern>
81                <!-- TODO: check: the names of referenced external components are not known, so we can't currently check if two or more of them use the same name -->
82            </xs:appinfo>
83        </xs:annotation>
84        <xs:sequence>
85            <xs:element name="Documentation" type="Documentation_type" minOccurs="0" maxOccurs="unbounded"/>
86            <!-- from small (attribute) to big (component) -->
87            <xs:element name="AttributeList" type="AttributeList_type" minOccurs="0" maxOccurs="1"/>
88            <xs:element name="Element" type="Element_type" minOccurs="0" maxOccurs="unbounded"/>
89            <xs:element name="Component" type="Component_type" minOccurs="0" maxOccurs="unbounded"/>
90        </xs:sequence>
91    </xs:group>
92
93    <!-- type definitions -->
94    <xs:complexType name="Documentation_type">
95        <xs:annotation>
96            <xs:documentation>Some information an application (eg Arbil) can display to give
97                guidance to the user when entering metadata.</xs:documentation>
98            <xs:appinfo>
99                <sch:pattern id="d_dsibs">
100                    <sch:title>Check Documentation siblings</sch:title>
101                    <sch:rule context="Documentation">
102                        <sch:assert test="empty(preceding-sibling::Documentation[@xml:lang=current()/@xml:lang])">Sibling Documentation elements should all be for different languages. Found multiple Documentation elements with xml:lang '<sch:value-of select="@xml:lang"/>'!</sch:assert>
103                    </sch:rule>
104                </sch:pattern>
105            </xs:appinfo>
106        </xs:annotation>
107        <xs:simpleContent>
108            <xs:extension base="xs:string">
109                <xs:attribute ref="xml:lang" use="optional"/>
110            </xs:extension>
111        </xs:simpleContent>
112    </xs:complexType>
113
114    <xs:complexType name="Element_type">
115        <xs:annotation>
116            <xs:appinfo>
117                <sch:pattern id="e_vs">
118                    <sch:title>Check Element ValueScheme</sch:title>
119                    <sch:rule context="Element">
120                        <sch:assert test="exists(@ValueScheme) or exists(ValueScheme)">An Element must have either a @ValueScheme or a ./ValueScheme!</sch:assert>
121                    </sch:rule>
122                </sch:pattern>
123            </xs:appinfo>
124        </xs:annotation>
125        <xs:sequence>
126            <xs:element name="Documentation" type="Documentation_type" minOccurs="0" maxOccurs="unbounded"/>
127            <xs:element name="AttributeList" type="AttributeList_type" minOccurs="0" maxOccurs="1">
128                <xs:annotation>
129                    <xs:documentation>The AttributeList child of an element contains a set of XML
130                        attributes for that element.</xs:documentation>
131                </xs:annotation>
132            </xs:element>
133            <xs:element minOccurs="0" maxOccurs="1" name="ValueScheme" type="ValueScheme_type">
134                <xs:annotation>
135                    <xs:documentation>When an element is linked to a regular expression or a
136                        controlled vocabulary, the ValueScheme sub-element contains more information
137                        about this.</xs:documentation>
138                </xs:annotation>
139            </xs:element>
140            <xs:element name="AutoValue" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
141        </xs:sequence>
142        <xs:attributeGroup ref="element_attributes"/>
143    </xs:complexType>
144
145    <xs:complexType name="ValueScheme_type">
146        <xs:annotation>
147            <xs:appinfo>
148                <sch:pattern id="v_uri">
149                    <sch:title>Check Vocabulary URI</sch:title>
150                    <sch:rule context="Vocabulary[exists(@URI)]">
151                        <sch:assert test="exists(@ValueProperty)">When an external vocabulary is used (identified by the @URI) a @ValueProperty has to be specified!</sch:assert>
152                    </sch:rule>
153                </sch:pattern>
154            </xs:appinfo>
155        </xs:annotation>
156        <xs:choice>
157            <xs:element name="pattern" type="xs:string" minOccurs="1" maxOccurs="1">
158                <xs:annotation>
159                    <xs:documentation>Specification of a regular expression the element should
160                        comply with.</xs:documentation>
161                </xs:annotation>
162            </xs:element>
163            <xs:element name="Vocabulary" type="Vocabulary_type" minOccurs="1" maxOccurs="1">
164                <xs:annotation>
165                    <xs:documentation>Specification of an open or closed vocabulary</xs:documentation>
166                </xs:annotation>
167            </xs:element>
168        </xs:choice>
169    </xs:complexType>
170
171    <xs:complexType name="Vocabulary_type">
172        <xs:sequence>
173            <xs:element name="enumeration" type="enumeration_type" minOccurs="0" maxOccurs="1">
174                <xs:annotation>
175                    <xs:documentation>A list of the allowed values of a controlled vocabulary.</xs:documentation>
176                </xs:annotation>
177            </xs:element>
178        </xs:sequence>
179        <xs:attribute name="URI" type="xs:anyURI" use="optional"/>
180        <!-- optionally selects a label -->
181        <xs:attribute name="ValueProperty" type="xs:string" use="optional"/>
182        <!-- optionally selects a language -->
183        <xs:attribute name="ValueLanguage" type="xs:language" use="optional"/>
184    </xs:complexType>
185
186    <xs:complexType name="AttributeList_type">
187        <xs:annotation>
188            <xs:appinfo>
189                <sch:pattern id="a_vs">
190                    <sch:title>Check Attribute ValueScheme</sch:title>
191                    <sch:rule context="Attribute">
192                        <sch:assert test="exists(@ValueScheme) or exists(ValueScheme)">An Attribute must have either a @ValueScheme or a ./ValueScheme!</sch:assert>
193                    </sch:rule>
194                </sch:pattern>
195            </xs:appinfo>
196        </xs:annotation>
197        <xs:sequence>
198            <xs:element name="Attribute" minOccurs="1" maxOccurs="unbounded">
199                <xs:annotation>
200                    <xs:appinfo>
201                        <sch:pattern id="a_res">
202                            <sch:title>Check reserved attribute names</sch:title>
203                            <sch:rule context="Attribute" role="warning">
204                                <sch:assert test="not(exists(parent::AttributeList/parent::Component) and @name=('ref','ComponentId'))">Attributes with name 'ref' or 'ComponentId' will not be available in a downgrade to CMDI 1.1!</sch:assert>
205                            </sch:rule>
206                        </sch:pattern>
207                        <sch:pattern id="a_sibs">
208                            <sch:title>Check attribute siblings</sch:title>
209                            <sch:rule context="Attribute">
210                                <sch:assert test="empty(preceding-sibling::Attribute[@name=current()/@name])">All attributes in an attribute list should have a different name. Found multiple attributes named '<sch:value-of select="Name"/>'!</sch:assert>
211                            </sch:rule>
212                        </sch:pattern>
213                    </xs:appinfo>
214                </xs:annotation>
215                <xs:complexType>
216                    <xs:sequence>
217                        <xs:element name="Documentation" type="Documentation_type" minOccurs="0" maxOccurs="unbounded"/>
218                        <xs:element name="ValueScheme" type="ValueScheme_type" minOccurs="0" maxOccurs="1">
219                            <xs:annotation>
220                                <xs:documentation>For the use of a regular expression or a
221                                    controlled vocabulary as the type of the
222                                    attribute.</xs:documentation>
223                            </xs:annotation>
224                        </xs:element>
225                        <xs:element name="AutoValue" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
226                    </xs:sequence>
227                    <xs:attributeGroup ref="attribute_attributes"/>
228                </xs:complexType>
229            </xs:element>
230        </xs:sequence>
231    </xs:complexType>
232
233    <xs:complexType name="Component_type">
234        <xs:group ref="group" minOccurs="0"/>
235        <xs:attributeGroup ref="component_attributes"/>
236    </xs:complexType>
237
238    <xs:attributeGroup name="attribute_attributes">
239        <xs:attribute name="name" type="xs:Name" use="required">
240            <xs:annotation>
241                <xs:documentation>The name of the attribute.</xs:documentation>
242            </xs:annotation>
243        </xs:attribute>
244        <xs:attribute name="ConceptLink" type="xs:anyURI" use="optional">
245            <xs:annotation>
246                <xs:documentation>A link to the ISOcat data category registry (or any other concept
247                    registry).</xs:documentation>
248            </xs:annotation>
249        </xs:attribute>
250        <xs:attribute name="ValueScheme" type="allowed_attributetypes_type" use="optional">
251            <xs:annotation>
252                <xs:documentation>For the use of simple XML types as the type of
253                    the attribute.</xs:documentation>
254            </xs:annotation>
255        </xs:attribute>
256        <xs:attribute name="Required" type="xs:boolean" use="optional">
257            <xs:annotation>
258                <xs:documentation>Is the attribute required or not?</xs:documentation>
259            </xs:annotation>
260        </xs:attribute>
261        <xs:anyAttribute namespace="http://www.clarin.eu/cmdi/cues/1" processContents="lax"/>
262    </xs:attributeGroup>
263
264    <xs:attributeGroup name="element_attributes">
265        <xs:attribute name="name" type="xs:Name" use="required">
266            <xs:annotation>
267                <xs:documentation>The name of the element.</xs:documentation>
268            </xs:annotation>
269        </xs:attribute>
270        <xs:attribute name="ConceptLink" type="xs:anyURI" use="optional">
271            <xs:annotation>
272                <xs:documentation>A link to the ISOcat data category registry (or any other concept
273                    registry).</xs:documentation>
274            </xs:annotation>
275        </xs:attribute>
276        <xs:attribute name="ValueScheme" type="allowed_attributetypes_type" use="optional">
277            <xs:annotation>
278                <xs:documentation>Used to specify that an element has a simple XML type (string,
279                    integer, etc)</xs:documentation>
280            </xs:annotation>
281        </xs:attribute>
282        <xs:attribute name="CardinalityMin" type="cardinality_type" use="optional" default="1">
283            <xs:annotation>
284                <xs:documentation>Minimal number of occurrences.</xs:documentation>
285            </xs:annotation>
286        </xs:attribute>
287        <xs:attribute name="CardinalityMax" type="cardinality_type" use="optional" default="1">
288            <xs:annotation>
289                <xs:documentation>Maximal number of occurrences.</xs:documentation>
290            </xs:annotation>
291        </xs:attribute>
292        <xs:attribute name="Multilingual" type="xs:boolean" use="optional">
293            <xs:annotation>
294                <xs:documentation>Indicates that this element can have values in multiple languages
295                    (and thus is repeatable). This will result in the possibility of using the
296                    xml:lang attribute in the metadata instances that are
297                created.</xs:documentation>
298            </xs:annotation>
299        </xs:attribute>
300        <xs:anyAttribute namespace="http://www.clarin.eu/cmdi/cues/1" processContents="lax"/>
301    </xs:attributeGroup>
302
303    <xs:attributeGroup name="component_attributes">
304        <xs:annotation>
305            <xs:appinfo>
306                <sch:pattern id="c_atts">
307                    <sch:title>Check component attributes</sch:title>
308                    <sch:rule context="Component">
309                        <sch:assert test="normalize-space(@name)!='' or normalize-space(@ComponentId)!=''">A Component should have a name or a ComponentId!</sch:assert>
310                    </sch:rule>
311                </sch:pattern>
312            </xs:appinfo>
313        </xs:annotation>
314        <xs:attribute name="name" type="xs:Name" use="optional"/>
315        <xs:attribute name="ComponentId" type="xs:anyURI" use="optional">
316            <xs:annotation>
317                <xs:documentation>Indicates that a component (using its unique ComponentId issued by
318                    the ComponentRegistry) should be included.</xs:documentation>
319            </xs:annotation>
320        </xs:attribute>
321        <xs:attribute name="ConceptLink" type="xs:anyURI" use="optional">
322            <xs:annotation>
323                <xs:documentation>A link to the ISOcat data category registry (or any other concept
324                    registry). Currently not used.</xs:documentation>
325            </xs:annotation>
326        </xs:attribute>
327        <xs:attribute name="CardinalityMin" type="cardinality_type" use="optional" default="1"/>
328        <xs:attribute name="CardinalityMax" type="cardinality_type" use="optional" default="1"/>
329        <xs:attribute ref="xml:base" use="optional"/>
330        <xs:anyAttribute namespace="http://www.clarin.eu/cmdi/cues/1" processContents="lax"/>
331    </xs:attributeGroup>
332
333
334    <xs:simpleType name="cardinality_type">
335        <xs:annotation>
336            <xs:documentation>cardinality for elements and components</xs:documentation>
337            <xs:appinfo>
338                <sch:pattern id="c_card">
339                    <sch:title>Check cardinalities</sch:title>
340                    <!--
341                        case minimum   maximum   check
342                        1    UNK       UNK       OK
343                        2    UNK       number    maximum ne 0
344                        3    UNK       unbounded OK
345                        4    number    UNK       minimum le 1
346                        5    number    number    minimum le maximum
347                        6    number    unbounded OK
348                        7    unbounded UNK       NOK
349                        8    unbounded number    NOK
350                        9    unbounded unbounded OK
351
352                        UNK can be either a missing attribute or an empty value, both can be detected with normalize-space(@...)=''
353
354                        default CardinalityMin is 1 (based on the XSD minOccurs default value)
355                        default CardinalityMax is 1 (based on the XSD maxOccurs default value)
356
357                        If a basic XSLT 2.0 engine, like Saxon HE, is used for Schematron validation we can't cast to xs:nonNegativeInteger.
358                        So we cast to xs:integer. The XSD validator should have already validated that the values are valid cardinality_types.
359                    -->
360                    <!-- skip case 1 -->
361                    <!-- case 2 -->
362                    <sch:rule context="*[(normalize-space(@CardinalityMin)='')][@CardinalityMax castable as xs:integer]">
363                        <sch:assert test="xs:integer(@CardinalityMax) ne 0">Maximum cardinality (0) cannot be lower than the default minimum cardinality (1)!</sch:assert>
364                    </sch:rule>
365                    <!-- skip case 3 -->
366                    <!-- case 4 -->
367                    <sch:rule context="*[@CardinalityMin castable as xs:integer][normalize-space(@CardinalityMax)='']">
368                        <sch:assert test="xs:integer(@CardinalityMin) le 1">Minimum cardinality (<sch:value-of select="@CardinalityMin"/>) should be lower or equal then the default maximum cardinality (1)!</sch:assert>
369                    </sch:rule>
370                    <!-- case 5 -->
371                    <sch:rule context="*[@CardinalityMin castable as xs:integer][@CardinalityMax castable as xs:integer]">
372                        <sch:assert test="xs:integer(@CardinalityMin) le xs:integer(@CardinalityMax)">Minimum cardinality (<sch:value-of select="@CardinalityMin"/>) should be lower or equal then the maximum cardinality (<sch:value-of select="@CardinalityMax"/>)!</sch:assert>
373                    </sch:rule>
374                    <!-- skip case 6 -->
375                    <!-- case 7, 8 and 9 -->
376                    <sch:rule context="*[@CardinalityMin='unbounded']">
377                        <!-- case 7 and 8 -->
378                        <sch:assert test="@CardinalityMax='unbounded'">Minimum cardinality (unbounded) can't be higher than the (default) maximum cardinality (<sch:value-of select="if (normalize-space(@CardinalityMax)='') then ('1') else (@CardinalityMax)"/>)!</sch:assert>
379                        <!-- skip case 9 -->
380                    </sch:rule>
381                </sch:pattern>
382            </xs:appinfo>
383        </xs:annotation>
384        <xs:union>
385            <xs:simpleType>
386                <xs:list itemType="xs:nonNegativeInteger"/>
387            </xs:simpleType>
388            <xs:simpleType>
389                <xs:restriction base="xs:string">
390                    <xs:enumeration value="unbounded"/>
391                </xs:restriction>
392            </xs:simpleType>
393        </xs:union>
394    </xs:simpleType>
395
396    <xs:simpleType name="allowed_attributetypes_type">
397        <xs:annotation>
398            <xs:documentation>Subset of XSD types that are allowed as CMD type</xs:documentation>
399        </xs:annotation>
400
401        <xs:restriction base="xs:token">
402            <xs:enumeration value="boolean"/>
403            <xs:enumeration value="decimal"/>
404            <xs:enumeration value="float"/>
405            <xs:enumeration value="int"/>
406            <xs:enumeration value="string"/>
407            <xs:enumeration value="anyURI"/>
408            <xs:enumeration value="date"/>
409            <xs:enumeration value="gDay"/>
410            <xs:enumeration value="gMonth"/>
411            <xs:enumeration value="gYear"/>
412            <xs:enumeration value="time"/>
413            <xs:enumeration value="dateTime"/>
414        </xs:restriction>
415    </xs:simpleType>
416
417    <xs:complexType name="enumeration_type">
418        <xs:annotation>
419            <xs:documentation>controlled vocabularies</xs:documentation>
420        </xs:annotation>
421        <xs:sequence>
422            <xs:element name="appinfo" type="xs:string" minOccurs="0" maxOccurs="1">
423                <xs:annotation>
424                    <xs:documentation>End-user guidance about the value of the controlled vocabulary
425                        as a whole. Currently not used.</xs:documentation>
426                </xs:annotation>
427            </xs:element>
428            <xs:element name="item" type="item_type" minOccurs="0" maxOccurs="unbounded">
429                <xs:annotation>
430                    <xs:documentation>An item from a controlled vocabulary.</xs:documentation>
431                </xs:annotation>
432            </xs:element>
433        </xs:sequence>
434    </xs:complexType>
435
436    <xs:complexType name="item_type">
437        <xs:annotation>
438            <xs:appinfo>
439                <sch:pattern id="item">
440                    <sch:title>CMD enumeration item</sch:title>
441                    <sch:rule context="item">
442                        <sch:assert test="empty(preceding-sibling::item[.=current()])">All items in an enumeration should be different. Found multiple items with value '<sch:value-of select="."/>'!</sch:assert>
443                    </sch:rule>
444                </sch:pattern>
445            </xs:appinfo>
446        </xs:annotation>
447        <xs:simpleContent>
448            <xs:extension base="xs:string">
449                <xs:attribute type="xs:anyURI" name="ConceptLink" use="optional">
450                    <xs:annotation>
451                        <xs:documentation>A link to the ISOcat data category registry (or any other
452                            concept registry) related to this controllec vocabulary
453                        item.</xs:documentation>
454                    </xs:annotation>
455                </xs:attribute>
456                <xs:attribute type="xs:string" name="AppInfo" use="optional">
457                    <xs:annotation>
458                        <xs:documentation>End-user guidance about the value of this controlled
459                            vocabulary item.</xs:documentation>
460                    </xs:annotation>
461                </xs:attribute>
462                <xs:anyAttribute namespace="http://www.clarin.eu/cmdi/cues/1" processContents="lax"/>
463            </xs:extension>
464        </xs:simpleContent>
465    </xs:complexType>
466
467</xs:schema>
Note: See TracBrowser for help on using the repository browser.