XMLType - smiffy.de

Transcription

XMLType - smiffy.de
Fakultät für Informatik & Wirtschaftsinformatik
DB & IS II - WS 2016
XMLType
Andreas Schmidt
XMLType 1/32
Fakultät für Informatik & Wirtschaftsinformatik
DB & IS II - WS 2016
XMLType
• von Oracle vordefinierter Typ zur Speicherung von nativen XML-Dokumenten
• unterstützt verschiedene Speichermodelle für XML
• structured storage (speicherung relational - nur mit XML-Schema möglich)
• binary xml storage (mit/ohne XML-Schema)
• unstructured storage (als CLOB)
• hybrid storage (mix aus obigen drei Modellen)
• Funktionen zur Unterstützung der SELECT-Anfragen auf XMLType Instanzen
• Funktionen zur Unterstützung der UPDATE-Operationen von XML-Dokumenten
• XML-Schema und XQuery Unterstützung
Andreas Schmidt
XMLType 2/32
Fakultät für Informatik & Wirtschaftsinformatik
DB & IS II - WS 2016
XMLType
Funktionen zur Unterstützung der SQL-Anfragen auf XMLType Instanzen:
•
•
•
•
•
extractValue(XMLType, XPath)
extract(XMLType, XPath)
existsNode(XMLType, XPath)
xmlsequence(XMLType)
table(XMLSequenceType)
Beispiel ... ->
Andreas Schmidt
XMLType 3/32
Fakultät für Informatik & Wirtschaftsinformatik
DB & IS II - WS 2016
Beispiel
create table xml_test (
id number primary key,
document xmltype not null
);
insert into xml_test (id, document)
values(1,xmltype('<land name="Deutschland">
<city>Karlsruhe</city>
<city>Stuttgart</city>
</land>'));
insert into xml_test (id, document)
values(2,xmltype('<land name="Frankreich">
<city>Strassburg</city>
<city>Marseille</city>
</land>'));
Andreas Schmidt
select *
from xml_test;
ID
DOCUMENT
----- -------------------1
<land name="Deutschland">
<city>Karlsruhe</city>
<city>Stuttgart</city>
</land>
2
<land name="Frankreich">
<city>Strassburg</city>
<city>Marseille</city>
</land>
2 Zeilen ausgewõhlt.
XMLType 4/32
Fakultät für Informatik & Wirtschaftsinformatik
DB & IS II - WS 2016
extractValue(...), existsNode(...)
• extractValue(...): liefert skalaren Wert (Zeichenkette, Number) eines Knotens zurück
select extractValue(document,'/land/@name')
from xml_test;
EXTRACTVALUE(DOCUMENT,'/LAND/@NAME')
---------------------------------------Deutschland
Frankreich
2 Zeilen ausgewõhlt.
• existsNode(...): liefert 1 zurück, wennn der XPath etwas zurückliefert, sonst 0
select extractValue(document,'/land/@name')
from xml_test
where existsNode(document,'//city[text()="Stuttgart"]')=1;
EXTRACTVALUE(DOCUMENT,'/LAND/@NAME')
---------------------------------------------Deutschland
1 Zeile wurde ausgewõhlt.
Andreas Schmidt
XMLType 5/32
Fakultät für Informatik & Wirtschaftsinformatik
DB & IS II - WS 2016
extract(...)
select extractValue(document,'//city')
from xml_test
where existsNode(document,'/land[@name="Frankreich"]')=1;
FEHLER in Zeile 2:
ORA-19025: EXTRACTVALUE gibt Wert von nur einem Knoten zur³ck
• extract(...): liefert XMLType Instanz zurück
select extract(document,'//city')
from xml_test
where existsNode(document,'/land[@name="Frankreich"]')=1;
EXTRACT(DOCUMENT,'//CITY')
------------------------------------------------xmltype(<city>Strassburg</city><city>Marseille</city>)
1 Zeile wurde ausgewõhlt.
Andreas Schmidt
XMLType 6/32
Fakultät für Informatik & Wirtschaftsinformatik
DB & IS II - WS 2016
xmlsequence(...)
• Frage: wie kann ich auf die einzelnen Städte zugreifen ?
aufspalten des XML-Fragments auf oberster Elementebene (Ergebnis: Liste)
select xmlsequence(extract(document,'//city'))
from xml_test
where existsNode(document,'/land[@name="Frankreich"]')=1;
XMLSEQUENCE(EXTRACT(DOCUMENT,'//CITY'))
-------------------------------------------------XMLSEQUENCETYPE(
XMLTYPE(<city>Strassburg</city>),
XMLTYPE(<city>Marseille</city>)
)
1 Zeile wurde ausgewõhlt.
Andreas Schmidt
XMLType 7/32
Fakultät für Informatik & Wirtschaftsinformatik
DB & IS II - WS 2016
table(...) - Operator
• wie komm ich an die einzelnen Felder der Liste ran ?
• table(...) Operator wandelt Liste in Tabelle um
select extractValue(column_value,'/city/text()')
from table ( select xmlsequence(extract(document,'//city'))
from xml_test
where existsNode(document,'/land[@name="Frankreich"]')=1 );
EXTRACTVALUE(COLUMN_VALUE,'/CITY/TEXT()')
---------------------------------------------------------Strassburg
Marseille
2 Zeilen ausgewõhlt.
Umwandlung einer Liste in eine Tabelle
Andreas Schmidt
XMLType 8/32
Fakultät für Informatik & Wirtschaftsinformatik
DB & IS II - WS 2016
Zusammenfassung Anfragen
• extract(...) liefert eine XMLType Instanz
• extractValue(...) liefert den skalaren Wert eines Knotens (werden mehrere Knoten
gefunden gibt es einen Fehler)
• mittels XMLSequence(...) kann eine XMLType Instanz auf der obersten Knotenebene aufgebrochen werden und es entsteht eine Liste aus XMLType Instanzen
• table(...) wandelt eine Liste in eine relationale Tabelle um, die dann weiter bearbeitet werden kann
• Pseudospalte column_value für den Zugriff auf die Datensätze einer mittels table(...)
erzeugten Tabelle
Andreas Schmidt
XMLType 9/32
Fakultät für Informatik & Wirtschaftsinformatik
DB & IS II - WS 2016
XMLType
Funktionen zur Unterstützung der Modifikationen von XML-Dokumenten
• updateXML: Führt ein Update eines Wertes/Elements/Attributs an der durch
XPath angegebenen Stelle durch.
• deleteXML: Löscht den/die durch den XPath angegebene(n) Elemente.
• insertXMLBefore: Fügt eine XMLType-Instanz vor der durch XPath spezifizierten Stelle ein.
• appendChildXML: Fügt eine XMLType-Instanz nach der durch den XPath
spezifizierten Stelle ein.
Beispiele ... ->
Andreas Schmidt
XMLType 10/32
Fakultät für Informatik & Wirtschaftsinformatik
DB & IS II - WS 2016
updateXML(...)
update xml_test
set document = updateXML(document,
'/land/@name','Bundesrepublik Deutschland',
'/land/city[text()="Stuttgart"]/text()','Stuttgart am Neckar')
where existsNode(document,'/land/@name[.="Deutschland"]')=1;
1 Zeile wurde aktualisiert.
select document
from xml_test
where existsNode(document,'/land/@name[.="Bundesrepublik Deutschland"]')=1;
DOCUMENT
-------------------------------------------------------------------<land name="Bundesrepublik Deutschland">
<city>Karlsruhe</city>
<city>Stuttgart am Neckar</city>
</land>
1 Zeile wurde ausgewõhlt.
Andreas Schmidt
XMLType 11/32
Fakultät für Informatik & Wirtschaftsinformatik
DB & IS II - WS 2016
appendChildXML(...)
update xml_test
set document=appendChildXML(document,
'/land',xmltype('<city>Dresden</city>'))
where existsNode(document,'/land/@name[.="Bundesrepublik Deutschland"]')=1;
1 Zeile wurde aktualisiert.
select document
from xml_test
where existsNode(document,'/land/@name[.="Bundesrepublik Deutschland"]')=1;
DOCUMENT
------------------------------------------------<land name="Bundesrepublik Deutschland">
<city>Karlsruhe</city>
<city>Stuttgart am Neckar</city>
<city>Dresden</city>
</land>
1 Zeile wurde ausgewõhlt.
Andreas Schmidt
XMLType 12/32
Fakultät für Informatik & Wirtschaftsinformatik
DB & IS II - WS 2016
insertChildXML(...) - Attribute
update xml_test
set document=insertChildXML(document,
'/land/city[text()="Dresden"]',
'@population','518081')
where existsNode(document,'/land/@name[.="Bundesrepublik Deutschland"]')=1;
1 Zeile wurde aktualisiert.
select document
from xml_test
where existsNode(document,'/land/@name[.="Bundesrepublik Deutschland"]')=1;
DOCUMENT
--------------------------------------------------<land name="Bundesrepublik Deutschland">
<city>Karlsruhe</city>
<city>Stuttgart am Neckar</city>
<city population="518081">Dresden</city>
</land>
1 Zeile wurde ausgewõhlt.
Andreas Schmidt
XMLType 13/32
Fakultät für Informatik & Wirtschaftsinformatik
DB & IS II - WS 2016
insertXMLBefore(...)
update xml_test
set document=insertXMLBefore(document,'/land/city[last()]',
xmltype('<city>Metropolis</city>'))
where existsNode(document,'/land/@name[.="Bundesrepublik Deutschland"]')=1;
1 Zeile wurde aktualisiert.
select document
from xml_test
where existsNode(document,'/land/@name[.="Bundesrepublik Deutschland"]')=1;
DOCUMENT
------------------------------------------------<land name="Bundesrepublik Deutschland">
<city>Karlsruhe</city>
<city>Stuttgart am Neckar</city>
<city>Metropolis</city>
<city population="518081">Dresden</city>
</land>
1 Zeile wurde ausgewõhlt.
Andreas Schmidt
XMLType 14/32
Fakultät für Informatik & Wirtschaftsinformatik
DB & IS II - WS 2016
deleteXML(...)
update xml_test
set document=deleteXML(document,'/land/city[text()="Metropolis"]')
where existsNode(document,'/land/@name[.="Bundesrepublik Deutschland"]')=1;
1 Zeile wurde aktualisiert.
select document
from xml_test
where existsNode(document,'/land/@name[.="Bundesrepublik Deutschland"]')=1;
DOCUMENT
---------------------------------------------------<land name="Bundesrepublik Deutschland">
<city>Karlsruhe</city>
<city>Stuttgart am Neckar</city>
<city population="518081">Dresden</city>
</land>
1 Zeile wurde ausgewõhlt.
Andreas Schmidt
XMLType 15/32
Fakultät für Informatik & Wirtschaftsinformatik
DB & IS II - WS 2016
deleteXML(...) - Attribute
update xml_test
set document=deleteXML(document,'/land/city[text()="Dresden"]/@population')
where existsNode(document,'/land/@name[.="Bundesrepublik Deutschland"]')=1;
1 Zeile wurde aktualisiert.
select document
from xml_test
where existsNode(document,'/land/@name[.="Bundesrepublik Deutschland"]')=1;
DOCUMENT
----------------------------------------------<land name="Bundesrepublik Deutschland">
<city>Karlsruhe</city>
<city>Stuttgart am Neckar</city>
<city>Dresden</city>
</land>
1 Zeile wurde ausgewõhlt.
Andreas Schmidt
XMLType 16/32
Fakultät für Informatik & Wirtschaftsinformatik
DB & IS II - WS 2016
Methode transform(...)
• Führt XSLT-Transformation auf XMLType Instanz aus
• Input: XSLT-Stylesheet
• Beispiel (Identity Stylesheet)
set long 1000
select document.transform(xmltype('<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>'))
from xml_test;
• Erläuterung: Das Identity-Stylesheet gibt den Input Text unverändert zurück. Durch Hinzunahme weiterer Regeln (xsl:template-Elemente) können dann bestimmte Teile modifiziert werden.
Andreas Schmidt
XMLType 17/32
Fakultät für Informatik & Wirtschaftsinformatik
DB & IS II - WS 2016
DTD und Schema Unterstützung
• DTD Unterstützung (Überprüfung erfolgt automatisch beim Einfügen)
insert into person_xml
values(XMLType('<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE Person [
<!ELEMENT Person (Name, Adresse)>
<!ATTLIST Person
ID CDATA #REQUIRED>
<!ELEMENT Adresse (Strasse, Plz, Ort)>
<!ELEMENT Name (#PCDATA)>
<!ELEMENT Strasse (#PCDATA)>
<!ELEMENT Plz (#PCDATA)>
<!ELEMENT Ort (#PCDATA)>
]>
<Person ID="242">
<Name>Sebbl Seeigel</Name>
<Adresse>
<Strasse>An der Mole 15</Strasse>
<Plz>65432</Plz>
<Ort>Salzhausen</Ort>
</Adresse>
</Person>'));
Andreas Schmidt
XMLType 18/32
Fakultät für Informatik & Wirtschaftsinformatik
DB & IS II - WS 2016
Schema Unterstützung
declare
str clob;
begin
str := '<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="Person">
<xs:complexType>
<xs:sequence>
<xs:element name="Name" type="xs:string"/>
<xs:element name="Adresse">
<xs:complexType>
<xs:sequence>
<xs:element name="Strasse" type="xs:string"/>
<xs:element name="Plz" type="xs:int"/>
<xs:element name="Ort" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute name="ID" type="xs:ID" use="required"/>
</xs:complexType>
</xs:element>
</xs:schema>';
dbms_xmlschema.registerSchema ('http://www.hs-karlsruhe.de/iwi/DB2/simple-person.xsd', str);
end;
/
Andreas Schmidt
XMLType 19/32
Fakultät für Informatik & Wirtschaftsinformatik
DB & IS II - WS 2016
Schema Unterstützung
• Tabelle, basierend auf XML-Schema definieren
create table person_schema_xml (
id number primary key,
document XMLType
) XMLType column document
XMLSCHEMA "http://www.hs-karlsruhe.de/iwi/DB2/simple-person.xsd"
ELEMENT "Person";
• Datensatz einfügen:
insert into person_schema_xml
values(1, XMLType('<Person ID="242">
<Name>Sebbl Seeigel</Name>
<Adresse>
<Strasse>An der Mole 15</Strasse>
<Plz>65432</Plz>
<Ort>Salzhausen</Ort>
</Adresse>
</Person>'));
Andreas Schmidt
XMLType 20/32
Fakultät für Informatik & Wirtschaftsinformatik
DB & IS II - WS 2016
Schema Unterstützung
• Keine defaultmäßige Überprüfung auf Schemakonformheit beim Eintrag/Update
• Dokument mit Fehler der nicht erkannt wird:
insert into person_schema_xml
values(2, XMLType('<Person ID="243">
<Name>Johann Meier</Name>
<Adresse/>
</Person>'));
Adresse muss laut Schema Unterelemente haben
Andreas Schmidt
XMLType 21/32
Fakultät für Informatik & Wirtschaftsinformatik
DB & IS II - WS 2016
Test für einen fehlerhaften Datensatz:
• Dokument mit Fehler der erkannt wird:
begin
Oracle weiss nicht was es mit Element
Anschrift tun soll (wohin speichern ?)
insert into person_schema_xml
values(3, XMLType('<Person ID="242">
<Name>Sebbl Seeigel</Name>
<Anschrift>
<Strasse>An der Mole 15</Strasse>
<Plz>65432</Plz>
<Ort>Salzhausen</Ort>
</Anschrift>
</Person>'));
dbms_output.put_line('FEHLER: keinen Fehler im XML Dokument gefunden !!');
exception
when others then
dbms_output.put_line('Fehler im XML Dokument erkannt');
end;
/
Andreas Schmidt
XMLType 22/32
Fakultät für Informatik & Wirtschaftsinformatik
DB & IS II - WS 2016
Validierung
• keine automatische Validierung gegenüber Schema !!
• Validierung mittels zusätzlicher Methoden:
• member function isSchemaValid(schema_url varchar2 := null,
element varchar2 := null)
return number
• static procedure schemaValidate(instance xmltype)
• Überprüfen/manuelles Setzen des Validierungsstatus
• member function isSchemaValidated() return number
• member procedure setSchemaValidated(flag IN BINARY_INTEGER := 1)
Andreas Schmidt
XMLType 23/32
Fakultät für Informatik & Wirtschaftsinformatik
DB & IS II - WS 2016
Validierung
• Überprüfung durch Instanzenmethode isSchemaValid(...)):
-- manuelles Überprüfen des Datensatzes
-declare
xmldoc xmltype;
begin
select document
into xmldoc
from person_schema_xml x
where existsNode(document,'/Person[@ID="243"]')=1;
IF xmldoc.isSchemaValid() = 1 THEN -- hier erfolgt die Validierung
dbms_output.put_line('Dokument wurde nicht beanstantet');
ELSE
dbms_output.put_line('Dokument wurde als falsch erkannt');
END IF;
end;
/
show errors
Andreas Schmidt
XMLType 24/32
Fakultät für Informatik & Wirtschaftsinformatik
DB & IS II - WS 2016
Validierung
• Überprüfung mittels Trigger:
CREATE TRIGGER is_valid_trig
BEFORE INSERT OR UPDATE ON person_schema_xml
FOR EACH ROW
DECLARE
newxml XMLType;
BEGIn
newxml := :new.document;
XMLTYPE.schemaValidate(newxml);
END;
/
Andreas Schmidt
XMLType 25/32
Fakultät für Informatik & Wirtschaftsinformatik
DB & IS II - WS 2016
XMLType und XQuery
• Zugriff auf Tabellen/Views mit Spalten vom Typ XMLType:
• 1.Schritt: Anlegen eines Views mit XMLType Spalte
create or replace view kleinstaaten (document)
as
select xmlelement("LAND", xmlattributes(code as "ID"),
xmlforest(capital, population))
from mondial.country c
where population < 100000;
• Test:
select document
from kleinstaaten;
• Ausgabe (Instanzen vom Typ XMLType):
<LAND ID="AND"><CAPITAL>Andorra la Vella</CAPITAL><POPULATION>72766</POPULATION></LAND>
<LAND ID="FL"><CAPITAL>Vaduz</CAPITAL><POPULATION>31122</POPULATION></LAND>
<LAND ID="MC"><CAPITAL>Monaco</CAPITAL><POPULATION>31719</POPULATION></LAND>
...
15 Zeilen ausgewählt.
Andreas Schmidt
XMLType 26/32
Fakultät für Informatik & Wirtschaftsinformatik
DB & IS II - WS 2016
• XQuery auf Datensätze im View kleinstaaten
select XMLquery('let $ks := /LAND
let $stadt:=$ks/CAPITAL/text()
let $id:=$ks/@ID
return <stadt land="{$id}">{$stadt}</stadt>'
PASSING document RETURNING CONTENT)
from kleinstaaten;
• Ausgabe (Instanzen vom Typ XMLType):
<stadt
<stadt
<stadt
<stadt
<stadt
<stadt
<stadt
...
land="AND">Andorra la Vella</stadt>
land="FL">Vaduz</stadt>
land="MC">Monaco</stadt>
land="V">Vatican City</stadt>
land="RSM">San Marino</stadt>
land="AG">Saint Johns</stadt>
land="WD">Roseau</stadt>
Input für XMLQuery Methode ist
die Spalte document des Views
kleinstaaten
15 Zeilen ausgewählt
Andreas Schmidt
XMLType 27/32
Fakultät für Informatik & Wirtschaftsinformatik
DB & IS II - WS 2016
XMLType und XQuery
• Anfrage:
select XMLquery('let $ks := /LAND
let $stadt:=$ks/CAPITAL/text()
let $id:=$ks/@ID
return <stadt land="{$id}">{$stadt}</stadt>'
PASSING document RETURNING CONTENT)
from kleinstaaten
where existsNode(document,'/LAND[POPULATION > 20000]')=1 ;
• Ausgabe (Instanzen vom Typ XMLType):
<stadt
<stadt
<stadt
<stadt
<stadt
...
land="AND">Andorra la Vella</stadt>
land="FL">Vaduz</stadt>
land="MC">Monaco</stadt>
land="V">Vatican City</stadt>
land="RSM">San Marino</stadt>
11 Zeilen ausgewählt.
Andreas Schmidt
XMLType 28/32
Fakultät für Informatik & Wirtschaftsinformatik
DB & IS II - WS 2016
XMLType und XQuery
• Anfrage:
select xmlagg(XMLquery('let $ks := /LAND
let $stadt:=$ks/CAPITAL/text()
let $id:=$ks/@ID
return <stadt land="{$id}">{$stadt}</stadt>'
PASSING document RETURNING CONTENT))
from kleinstaaten
where existsNode(document,'/LAND[POPULATION > 20000]')=1 ;
• Ausgabe (Instanz vom Typ XMLType):
<stadt land="AND">Andorra la Vella</stadt><stadt land="FL">Vaduz</stadt><stadt \
land="MC">Monaco</stadt><stadt land="RSM">San Marino</stadt><stadt land="AG">Saint \
Johns</stadt><stadt land="WD">Roseau</stadt><stadt land="WG">Saint Georges</stadt><stadt\
land="KN">Basseterre</stadt><stadt land="KIR">Tarawa</stadt><stadt land="MH">Majuro\
</stadt><stadt land="SY">Victoria</stadt>
1 Zeilen ausgewählt.
Andreas Schmidt
XMLType 29/32
Fakultät für Informatik & Wirtschaftsinformatik
DB & IS II - WS 2016
Typtransformationen
• extract(), XMLElement(), XMLAttributes(), XMLRoot(),
XMLAgg(), XMLQuery() liefern jeweils eine XMLType Instanz als Ergebnis
zurück.
• Transformation von XMLType in konkreten Datentyp mittels folgender Methoden:
• getClobVal(): liefert XMLType Instanz als CLOB
• getStringVal(): Liefert XMLType-Instanz als Zeichenkette
• getNumberVal(): Liefert Wert einer XMLType-Instanz als numerischen Wert
zurück (XMLType Instanz muss Textknoten mit numerischem Inhalt sein)
• Beispiel:
select extract(xmltype('<x>12</x>'),'/x/text()').getNumberVal()
from dual;
-- neue Notation:
-select xmltype('<x>12</x>').extract('/x/text()').getNumberVal()
Andreas Schmidt
XMLType 30/32
Fakultät für Informatik & Wirtschaftsinformatik
DB & IS II - WS 2016
Literatur/Quellen:
• Anlegen von typisierten Views:
http://www.stanford.edu/dept/itss/docs/oracle/10g/appdev.101/b10790/xdb14vie.htm
• Querying, Constructing, and Transforming XML with Oracle XQuery
http://www.oracle.com/technology/pub/articles/vasiliev_xquery.html
• Towards an industrial strength SQL/XML Infrastructure
http://www.oracle.com/technology/tech/xml/xquery/pdf/
ICDE2005_industrial_strength_sqlxml.pdf
• Leseproben xquery buch (dpunkt verlag)
http://www.dpunkt.de/buch/3-89864-266-6.html
• How To: Oracle XML DB:
http://www.doag.org/pub/docs/konferenz/2004/vortraege/oraclexmldb.pdf
• oracle-faq:
http://www.orafaq.com/faqxml.htm
Andreas Schmidt
XMLType 31/32
Fakultät für Informatik & Wirtschaftsinformatik
DB & IS II - WS 2016
Literatur/Resourcen
• XML in der oracle-datenbank - relational and beyond:
http://doesen0.informatik.uni-leipzig.de/proceedings/paper/IP6.pdf
• Oracle, Java, XML - Integration in Oracle9iM; Rudolf Jansen ; Software & Support Verlag
GmbH; 2004; 60 Seiten; ISBN 3-935042-33-7; Preis: 39.90 EUR
• XML & Datenbanken - Konzepte, Sprachen und Systeme; Meike Klettke / Holger Meyer;
dpunkt.verlag; Dezember 2002; 444 Seiten, Broschur; 42 Euro; ISBN 3-89864-148-1
• XMLType:
http://download.oracle.com/docs/cd/B19306_01/appdev.102/b14258/t_xml.htm
• Vorlesung (inkl. Skript) Einführung in XML (Prof. Wegner, Uni Kassel)
http://www.db.informatik.uni-kassel.de/Lehre/WS0405/XML
Andreas Schmidt
XMLType 32/32