Python script to validate WIPO ST.92 Priority Document Data Packages (PDDP ZIP files) before REGISTRATION of priority documents in WIPO DAS REST API V2. It works with packages created by the generator (4.- Generating PDDP samples for testing) and with packages produced by any other system.
Disclaimer
This is a helper tool for testing. It does not replace the validation performed by WIPO DAS and does not cover every rule of ST.92.
Get the validator here: PDDP_Validator.zip (version of 02.10.2026)
Contents of the package
validatorPddp/
├── validate_pddp.py # Validator script
├── requirements.txt # Python dependency (lxml)
├── README.md # Documentation
├── xsd/ # Offline fallback copy of the ST.92 V2.0 schemas
│ ├── ST92PDDPIndex_V2_0.xsd
│ ├── ST96_Common_V9_0.xsd
│ ├── ST96_Design_V9_0.xsd
│ └── ST96_Trademark_V9_0.xsd
└── dtd/
└── ST26SequenceListing_V1_3.dtd # WIPO ST.26 DTD for sequence listings
By default the validator downloads the schemas directly from WIPO, so it always checks against the published versions:
- ST.92 index schema: ST92PDDPIndex_V2_0.xsd (its three ST.96 imports are resolved automatically)
- ST.96 V9.0 schemas, used for the supplementary artifacts: ST96XMLSchema_V9_0_Flattened.zip
Downloads are cached under .cache/ and reused on later runs. If a download fails, the validator falls back to the bundled xsd/ copy and reports that it did. Use --offline to force the bundled copy and never touch the network; those files are byte-identical to the published ones, so both modes validate against the same schema.
The ST.26 DTD is only distributed inside the ST.26 Annex II bundle and has no stable standalone URL, so it stays in dtd/.
Installation
The validator needs Python 3.10+ and the lxml library (XSD/DTD validation is not available in the Python standard library).
# Linux / macOS cd validatorPddp python3 -m venv .venv .venv/bin/pip install -r requirements.txt # Windows (PowerShell) cd validatorPddp py -m venv .venv .venv\Scripts\pip install -r requirements.txt
On Debian / Ubuntu / Raspberry Pi OS you can instead install the system package: sudo apt install python3-lxml.
Usage
# Validate all ZIP files in ../output (default) .venv/bin/python validate_pddp.py # Validate specific ZIP files and/or all ZIP files in a folder .venv/bin/python validate_pddp.py Patent_NO_20210008_20210924.zip ./received/ # Also list every check that passed .venv/bin/python validate_pddp.py -v ./output # Report advisory findings as warnings instead of errors .venv/bin/python validate_pddp.py --lenient ./output # Use the bundled schemas, without any network access .venv/bin/python validate_pddp.py --offline ./output
All options
| Option | Default | Description |
|---|---|---|
paths ... | ../output | ZIP files and/or folders containing ZIP files |
-v, --verbose | off | Also list the checks that passed |
--schema URL|FILE | the WIPO URL above | ST.92 index schema to validate against |
--offline | off | Use the bundled xsd/ copy, never touch the network |
--refresh-schema | off | Re-download the schemas, ignoring the cache |
--no-fallback | off | Fail instead of falling back to the bundled schema |
--timeout SECONDS | 30 | Schema download timeout |
--st96-schema URL | the WIPO ST.96 zip above | Flattened ST.96 release for supplementary artifacts |
--st96-dir DIR | - | Use an already-extracted ST.96 schema folder |
--no-st96 | off | Skip ST.96 validation of supplementary artifacts |
--lenient | off | Report advisory findings as warnings instead of errors |
--st26-dtd FILE | dtd/ST26SequenceListing_V1_3.dtd | ST.26 sequence listing DTD |
Strict by default: advisory findings are reported as errors, so nothing is silently accepted. Pass --lenient to keep them as warnings.
Exit code: 0 when no package has errors, 1 otherwise (can be used in scripts / CI).
Checks performed
| Group | Check | Result if it fails |
|---|---|---|
| Archive | ZIP opens and every entry passes its CRC | ERROR |
| Archive | No encrypted entries and no duplicate entry names | ERROR |
| Archive | No absolute paths, .. traversal, backslashes or control characters in entry names | ERROR |
| Archive | PriorityDocumentIndex.xml present at the ZIP root, with exact casing | ERROR |
| Index | Well-formed XML, parsed with entity expansion and network access disabled | ERROR |
| Index | No DOCTYPE and no XML entity references | ERROR |
| Index | Root element is pde:PriorityDocumentIndex | ERROR |
| Index | Valid against ST92PDDPIndex_V2_0.xsd | ERROR |
| Index | Document categories match IPRightKindCategory | ERROR |
| Index | Mandatory documents present: priority document PDF (all types), certification page and representation (designs, trademarks) | ERROR |
| Index | Patent package without a separate certification page (it must then be part of the priority document PDF) | advisory |
| Index | Supplementary document category is one of the values ST.92 recommends for the IP right type. Mandatory categories are a closed enumeration enforced by the schema, but supplementary ones are declared as a union with xsd:token, so the schema accepts any value and a typo would otherwise pass unnoticed | advisory |
| Index | ApplicationFilingDate and DocumentDate parse and are not in the future | ERROR |
| Index | ZIP name <Kind>_<Office>_<Number>_<YYYYMMDD>.zip matches the index | ERROR / advisory |
| References | Every file listed in the index exists in the ZIP | ERROR |
| References | com:FileName contains no path component | ERROR |
| References | DocumentLocationURI is relative and does not escape the package | ERROR |
| References | Mandatory documents live under MandatoryArtifacts/, supplementary under SupplementaryArtifacts/ | ERROR |
| References | DocumentLocationURI is an external URL; file in the ZIP not listed in the index; one file referenced by several entries | advisory |
| Content | No empty files | ERROR |
| Content | Declared DocumentFileFormatCategory matches both the file extension and the actual bytes | ERROR |
| Content | File content matches its extension (PDF, PNG, JPEG, WAV, MP3, STL, ZIP, TAR, XML) | ERROR |
| Content | PDF structure: header, startxref, %%EOF, /Root | ERROR |
| Content | PNG structure: per-chunk CRCs, IHDR/IDAT/IEND present, non-zero dimensions | ERROR |
| Content | WAV structure: RIFF size agrees with the file, fmt and data chunks present and in bounds | ERROR |
| Content | STL structure: facet / loop / vertex counts agree (ASCII) or size matches the triangle count (binary) | ERROR |
| Content | Zipped artifacts open, are unencrypted and CRC-clean | ERROR |
| Content | PageTotalQuantity matches the PDF page count; DocumentSizeQuantity matches the real byte size | advisory |
| Content | Internal XML is well-formed | ERROR |
| Content | Supplementary artifacts valid against the published ST.96 V9.0 schemas | ERROR |
| Content | ST.26 sequence listings valid against the ST.26 DTD | ERROR |
| Content | ST.26 cross-checks: fileName, SequenceTotalQuantity, sequenceIDNumber runs 1..n, INSDSeq_length matches the sequence | ERROR |
| Content | ST.26 characters within the Annex IV Basic Latin subset | advisory |
| Content | ST.25 sequence listings: mandatory numeric identifiers present, <160> matches the sequence count, <210> runs 1..n, <212> is DNA/RNA/PRT, ASCII only | ERROR |
| Content | ST.25 used only on applications filed before 2022-07-01 | ERROR |
Checks marked advisory are reported as errors by default and as warnings with --lenient.
Bibliographic and classification data (ST.96)
Bibliographic and classification data are now validated against the published ST.96 V9.0 schemas, not just checked for well-formedness.
Note that these documents belong to the per-right ST.96 namespaces, not to Common: pat:BibliographicData and pat:PatentClassificationBag for patents, dgn:DesignApplication and com:DesignClassificationBag (Locarno) for designs, tmk:TrademarkApplication and tmk:GoodsServicesBag (Nice) for trademarks.
The trimmed ST96_Common_V9_0.xsd shipped inside the ST.92 Annex I bundle declares only 16 global elements, a subset built for the index schema. It is not a substitute for the full ST.96 Common namespace, which is why the supplementary artifacts are checked against the ST.96 release instead.
Document categories: mandatory is closed, supplementary is open
pde:*MandatoryDocumentCategory is declared with xsd:restriction, so only these values are valid and xmllint rejects anything else:
| Patent | Industrial design | Trademark |
|---|---|---|
| Certification page | Certification page | Certification page |
| Priority document PDF | Priority document PDF | Priority document PDF |
| Sequence listing | Industrial design representation | Trademark representation |
pde:*SupplementaryDocumentCategory is declared as a union of xsd:token and a base type, so the enumerated values are recommended rather than binding and an Office may legitimately use another token. The validator therefore reports an unrecognised supplementary category as advisory, to catch typos without blocking legitimate values:
| Patent | Industrial design | Trademark |
|---|---|---|
| Abstract | Bibliographic data | Bibliographic data |
| Application body | Registration certificate | Registration certificate |
| Bibliographic data | Industrial design representation | Mark representation |
| Description | Classification data | Classification data |
| Claims | Intermediate documents | Intermediate documents |
| Drawings | ||
| Classification data | ||
| Preconversion document | ||
| Sequence listing |
Note that com:DocumentName beside these elements is free text (xsd:string union) and carries no controlled vocabulary; the category element is the machine-readable one.
Sequence listings: ST.26 and ST.25
ST.92 paragraph 18 permits ST.26, ST.25 or ST.23, and footnote 2 makes ST.26 mandatory for patent applications filed on or after 1 July 2022. The validator reads pde:ApplicationFilingDate from the index and rejects an ST.25 listing on a later filing:
ERROR ..._SequenceListing_ST25.txt: ST.25 sequence listing on an application
filed 2023-03-15. ST.26 (XML) is mandatory for patent applications
filed on or after 2022-07-01.
ST.25 listings are recognised by their numeric identifiers rather than by file name, so a listing named anything else is still checked. The expected DocumentFileFormatCategory is TEXT for ST.25 and XML for ST.26.
Example output
>>>> .venv/bin/python validate_pddp.py -v ./output/Patent_IB_PCT-IB2026-134592_20260103.zip
ST.92 schema: https://www.wipo.int/standards/XMLSchema/ST92/V2_0/ST92PDDPIndex_V2_0.xsd
ST.96 schema: https://www.wipo.int/standards/en/st96/v9-0/annex-iii/ST96XMLSchema_V9_0_Flattened.zip
Mode: strict
[OK] Patent_IB_PCT-IB2026-134592_20260103.zip
ok ZIP integrity OK
ok 11 ZIP entr(ies), all names safe and unique
ok PriorityDocumentIndex.xml valid against the ST.92 V2.0 schema
ok Document categories consistent with 'Patent'
ok Mandatory documents present: ['Certification page', 'Priority document PDF', 'Sequence listing']
ok ZIP file name consistent with index
ok All 7 referenced files resolved
ok MandatoryArtifacts/..._PriorityDocument.pdf: PDF OK (2,847 bytes, 3 page(s))
ok MandatoryArtifacts/..._SequenceListing_ST26.xml: valid against the ST.26 DTD
ok SupplementaryArtifacts/..._BibliographicData.xml: valid against ST.96 V9.0 (BibliographicData_V9_0.xsd)
ok SupplementaryArtifacts/..._ClassificationData.xml: valid against ST.96 V9.0 (Patent_V9_0.xsd)
1 package(s) checked: 1 passed, 0 failed.
Without -v only problems are listed:
>>>> .venv/bin/python validate_pddp.py ./received/
[FAIL] Patent_XX_1234567_20260101.zip
ERROR MandatoryArtifacts/doc.pdf: declared format 'PNG' does not match extension '.pdf' (expected ['.png'])
ERROR SupplementaryArtifacts/bib.xml ST.96: line 11: Element 'InventionTitle': This element is not expected. Expected is ( InventionTitleBag ).
1 package(s) checked: 0 passed, 1 failed.
Common errors
| Message | Cause / fix |
|---|---|
SupplementaryDocumentBag': Missing child element(s) | An empty <pde:SupplementaryDocumentBag> is not allowed. Remove the element if there are no supplementary documents. |
'Text' is not a valid value of the union type ... DocumentFileFormatCategoryType | File format values are case sensitive: use TEXT, PDF, XML, … |
No declaration for element INSDSeq_organism | Not part of ST.26. The organism must be given as the organism qualifier of the source feature. |
<PatentBibliographicData> is not a global element | There is no such element in the ST.96 Common namespace. Bibliographic data belongs to the per-right namespaces: pat:BibliographicData, dgn:DesignApplication, tmk:TrademarkApplication. |
declared format 'X' does not match extension '.y' | DocumentFileFormatCategory disagrees with the file it points at. Fix whichever is wrong. |
PageTotalQuantity N != M page(s) found in the PDF | The declared page count does not match the PDF. Advisory, so it only fails the run in strict mode. |
mandatory document stored under SupplementaryArtifacts/ | Mandatory artifacts must sit under MandatoryArtifacts/ and supplementary ones under SupplementaryArtifacts/. |
Path traversal in ZIP entry | The package contains an entry with .. or an absolute path. Rebuild it with relative paths only. |
ST.25 sequence listing on an application filed ... | The package pairs an ST.25 listing with a filing date on or after 1 July 2022. Supply the listing in ST.26 (XML) instead. |
unrecognised DocumentFileFormatCategory 'TXT' | ST.96 enumerates the plain-text category as TEXT, not TXT. |
content is not a valid STL/PDF/... file | The file does not contain what its extension says (e.g. an HTML page saved with a .stl extension). |
Requirements
Python 3.10+ and lxml.
Network access to www.wipo.int is used to fetch the schemas on first run. Behind a proxy or offline, run with --offline to use the bundled copies.