-
Notifications
You must be signed in to change notification settings - Fork 5
Clarify decimal datatype constraints and simplify validation #135
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 3 commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
385c311
Clarify decimal datatype constraints and simplify validation.
david-waltermire 23b7f3b
Update decimal datatype to use xs:double base and support exponential…
david-waltermire 962d4c2
Address PR review feedback for decimal datatype
david-waltermire 8fd3316
Replace compiled class file with Maven POM for test utilities
david-waltermire edb9c6c
Add file existence checks to XmlValidator for clearer error messages
david-waltermire 9dc8197
Harden XmlValidator against XXE attacks
david-waltermire File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,57 @@ | ||
| # Decimal Datatype Test Cases | ||
|
|
||
| This directory contains test schemas and content examples to validate the decimal datatype behavior as defined in PR #135. | ||
|
|
||
| ## Schemas | ||
|
|
||
| - `decimal-test.xsd` - XML Schema with inline DecimalDatatype using pattern `-?(0|[1-9][0-9]*)(\.[0-9]+)?([eE][+-]?[0-9]+)?` and base type `xs:double` | ||
| - `decimal-test.json` - JSON Schema with inline DecimalDatatype using `type: "number"` | ||
|
|
||
| ## Expected Behavior Matrix (Tested) | ||
|
|
||
| | Test Case | Example | JSON | XML | | ||
| |-----------|---------|:----:|:---:| | ||
| | Integers | `12` | ✓ | ✓ | | ||
| | Decimals | `12.34` | ✓ | ✓ | | ||
| | Positive with leading + | `+12.34` | ✗ | ✗ | | ||
| | Exponential notation | `1e3`, `1E+4`, `-2.5e-10` | ✓ | ✓ | | ||
| | Leading zeros | `01.23` | ✗ | ✗ | | ||
| | No leading digit | `.47` | ✗ | ✗ | | ||
| | Trailing decimal point | `123.` | ✗ | ✗ | | ||
| | Leading/trailing whitespace | ` 12.34 ` | ✓ | ✓ | | ||
|
|
||
| **Legend:** ✓ = Valid, ✗ = Invalid | ||
|
|
||
| ### Notes | ||
|
|
||
| Both JSON and XML ignore/normalize whitespace around numeric values, so leading/trailing whitespace is accepted in both formats. | ||
|
|
||
| ## Test Files | ||
|
|
||
| ### XML Test Cases | ||
|
|
||
| - `xml-valid-cases.xml` - Contains values that SHOULD pass XML Schema validation | ||
| - `xml-invalid-cases.xml` - Contains commented-out invalid cases for individual testing | ||
|
|
||
| ### JSON Test Cases | ||
|
|
||
| - `json-valid-cases.json` - Contains values that SHOULD pass JSON Schema validation | ||
| - `json-invalid-cases.json` - Documents invalid cases (many cannot be represented in valid JSON syntax) | ||
|
|
||
| ## Key Differences Between JSON and XML | ||
|
|
||
| 1. **Whitespace Handling**: Both XML Schema and JSON ignore whitespace around numeric values. XML Schema applies whitespace normalization (collapse) for `xs:double` before pattern matching. JSON ignores whitespace around values during parsing. | ||
|
|
||
| 2. **Syntax Restrictions**: JSON syntax itself prohibits leading `+`, leading zeros (e.g., `01.23`), `.47`, and `123.` formats, making these parse errors rather than validation errors. The XML pattern explicitly rejects these as well. | ||
|
|
||
| ## Running Validation Tests | ||
|
|
||
| ### XML Validation (using xmllint) | ||
| ```bash | ||
| xmllint --schema decimal-test.xsd xml-valid-cases.xml --noout | ||
| ``` | ||
|
|
||
| ### JSON Validation (using ajv-cli) | ||
| ```bash | ||
| ajv validate -s decimal-test.json -d json-valid-cases.json | ||
| ``` |
|
david-waltermire marked this conversation as resolved.
Outdated
|
Binary file not shown.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| import javax.xml.XMLConstants; | ||
| import javax.xml.transform.stream.StreamSource; | ||
| import javax.xml.validation.Schema; | ||
| import javax.xml.validation.SchemaFactory; | ||
| import javax.xml.validation.Validator; | ||
|
coderabbitai[bot] marked this conversation as resolved.
|
||
| import java.io.File; | ||
|
|
||
| public class XmlValidator { | ||
| public static void main(String[] args) { | ||
| if (args.length < 2) { | ||
| System.out.println("Usage: java XmlValidator <schema.xsd> <document.xml>"); | ||
| System.exit(1); | ||
| } | ||
|
|
||
| String schemaPath = args[0]; | ||
| String xmlPath = args[1]; | ||
|
|
||
| try { | ||
| SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); | ||
| Schema schema = factory.newSchema(new File(schemaPath)); | ||
| Validator validator = schema.newValidator(); | ||
| validator.validate(new StreamSource(new File(xmlPath))); | ||
| System.out.println(xmlPath + " is VALID"); | ||
| } catch (Exception e) { | ||
| System.out.println(xmlPath + " is INVALID: " + e.getMessage()); | ||
| System.exit(1); | ||
| } | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| { | ||
| "$schema": "http://json-schema.org/draft-07/schema#", | ||
| "$id": "http://csrc.nist.gov/ns/metaschema/test/decimal/decimal-test-schema.json", | ||
| "$comment": "Schema for testing decimal datatype validation", | ||
| "type": "object", | ||
| "properties": { | ||
| "decimal-tests": { | ||
| "type": "object", | ||
| "properties": { | ||
| "test-cases": { | ||
| "type": "array", | ||
| "items": { | ||
| "type": "object", | ||
| "properties": { | ||
| "id": { | ||
| "type": "string" | ||
| }, | ||
| "description": { | ||
| "type": "string" | ||
| }, | ||
| "expected": { | ||
| "type": "string", | ||
| "enum": ["valid", "invalid"] | ||
| }, | ||
| "value": { | ||
| "description": "A real number expressed using a whole and optional fractional part separated by a period, with optional exponential notation. No leading '+' is allowed.", | ||
| "type": "number" | ||
|
coderabbitai[bot] marked this conversation as resolved.
|
||
| } | ||
| }, | ||
| "required": ["id", "description", "expected", "value"] | ||
| } | ||
| } | ||
| }, | ||
| "required": ["test-cases"] | ||
| } | ||
| }, | ||
| "required": ["decimal-tests"] | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,46 @@ | ||
| <?xml version="1.0" encoding="utf-8"?> | ||
| <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" | ||
| xmlns:m="http://csrc.nist.gov/ns/metaschema/test/decimal" | ||
| targetNamespace="http://csrc.nist.gov/ns/metaschema/test/decimal" | ||
| elementFormDefault="qualified"> | ||
|
|
||
| <!-- Root element for testing --> | ||
| <xs:element name="decimal-tests"> | ||
| <xs:complexType> | ||
| <xs:sequence> | ||
| <xs:element name="test-case" maxOccurs="unbounded"> | ||
| <xs:complexType> | ||
| <xs:sequence> | ||
| <xs:element name="value"> | ||
| <xs:simpleType> | ||
| <xs:annotation> | ||
| <xs:documentation> | ||
| A real number expressed using a whole and optional fractional part | ||
| separated by a period, with optional exponential notation. | ||
| No leading '+' is allowed. Leading zeros are not allowed except | ||
| for the integer 0 itself or numbers less than 1 (e.g., 0.5). | ||
| </xs:documentation> | ||
| </xs:annotation> | ||
| <xs:restriction base="xs:double"> | ||
| <xs:pattern value="-?(0|[1-9][0-9]*)(\.[0-9]+)?([eE][+-]?[0-9]+)?"/> | ||
| </xs:restriction> | ||
| </xs:simpleType> | ||
| </xs:element> | ||
| </xs:sequence> | ||
| <xs:attribute name="id" type="xs:string" use="required"/> | ||
| <xs:attribute name="description" type="xs:string" use="required"/> | ||
| <xs:attribute name="expected" use="required"> | ||
| <xs:simpleType> | ||
| <xs:restriction base="xs:string"> | ||
| <xs:enumeration value="valid"/> | ||
| <xs:enumeration value="invalid"/> | ||
| </xs:restriction> | ||
| </xs:simpleType> | ||
| </xs:attribute> | ||
| </xs:complexType> | ||
| </xs:element> | ||
| </xs:sequence> | ||
| </xs:complexType> | ||
| </xs:element> | ||
|
|
||
| </xs:schema> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,47 @@ | ||
| { | ||
| "$schema": "decimal-test.json", | ||
| "_comment": "Invalid decimal test cases for JSON validation. These values SHOULD FAIL JSON Schema validation or are invalid JSON syntax.", | ||
| "_note": "JSON does not allow: leading +, leading/trailing whitespace, .47 syntax, 123. syntax. These would be syntax errors or string values.", | ||
| "decimal-tests": { | ||
| "test-cases": [ | ||
| { | ||
| "id": "json-placeholder", | ||
| "description": "Placeholder - see comments below for invalid cases that cannot be represented in JSON", | ||
| "expected": "valid", | ||
| "value": 0 | ||
| } | ||
| ] | ||
| }, | ||
| "_invalid_cases_documentation": { | ||
| "leading_plus": { | ||
| "example": "+12.34", | ||
| "reason": "JSON syntax does not allow leading + on numbers. This would be a parse error.", | ||
| "expected": "invalid" | ||
| }, | ||
| "leading_zeros": { | ||
| "example": "01.23", | ||
| "reason": "JSON syntax does not allow leading zeros on numbers (except 0 itself). This would be a parse error.", | ||
| "expected": "invalid" | ||
| }, | ||
| "no_leading_digit": { | ||
| "example": ".47", | ||
| "reason": "JSON syntax requires a digit before the decimal point. This would be a parse error.", | ||
| "expected": "invalid" | ||
| }, | ||
| "trailing_decimal": { | ||
| "example": "123.", | ||
| "reason": "JSON syntax requires digits after the decimal point. This would be a parse error.", | ||
| "expected": "invalid" | ||
| }, | ||
| "leading_whitespace": { | ||
| "example": " 12.34", | ||
| "reason": "If represented as a string \" 12.34\", it would fail type: number validation.", | ||
| "expected": "invalid" | ||
| }, | ||
| "trailing_whitespace": { | ||
| "example": "12.34 ", | ||
| "reason": "If represented as a string \"12.34 \", it would fail type: number validation.", | ||
| "expected": "invalid" | ||
| } | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| { | ||
| "$schema": "decimal-test.json", | ||
| "decimal-tests": { | ||
| "test-cases": [ | ||
| { | ||
| "id": "json-string-with-whitespace", | ||
| "description": "String value with whitespace should fail type: number", | ||
| "expected": "invalid", | ||
| "value": " 12.34 " | ||
| } | ||
| ] | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,68 @@ | ||
| { | ||
| "$schema": "decimal-test.json", | ||
| "_comment": "Valid decimal test cases for JSON validation. All values SHOULD pass JSON Schema validation with type: number", | ||
| "decimal-tests": { | ||
| "test-cases": [ | ||
| { | ||
| "id": "json-int-positive", | ||
| "description": "Positive integer (e.g., 12)", | ||
| "expected": "valid", | ||
| "value": 12 | ||
| }, | ||
| { | ||
| "id": "json-int-negative", | ||
| "description": "Negative integer", | ||
| "expected": "valid", | ||
| "value": -42 | ||
| }, | ||
| { | ||
| "id": "json-int-zero", | ||
| "description": "Zero", | ||
| "expected": "valid", | ||
| "value": 0 | ||
| }, | ||
| { | ||
| "id": "json-dec-positive", | ||
| "description": "Positive decimal (e.g., 12.34)", | ||
| "expected": "valid", | ||
| "value": 12.34 | ||
| }, | ||
| { | ||
| "id": "json-dec-negative", | ||
| "description": "Negative decimal", | ||
| "expected": "valid", | ||
| "value": -12.34 | ||
| }, | ||
| { | ||
| "id": "json-dec-small", | ||
| "description": "Small decimal", | ||
| "expected": "valid", | ||
| "value": 0.001 | ||
| }, | ||
| { | ||
| "id": "json-exp-lower", | ||
| "description": "Exponential notation lowercase (e.g., 1e3) - Valid in JSON", | ||
| "expected": "valid", | ||
| "value": 1e3 | ||
| }, | ||
| { | ||
| "id": "json-exp-upper-plus", | ||
| "description": "Exponential notation uppercase with plus (e.g., 1E+4) - Valid in JSON", | ||
| "expected": "valid", | ||
| "value": 1E+4 | ||
| }, | ||
| { | ||
| "id": "json-exp-negative", | ||
| "description": "Exponential notation negative (e.g., -2.5e-10) - Valid in JSON", | ||
| "expected": "valid", | ||
| "value": -2.5e-10 | ||
| }, | ||
| { | ||
| "id": "json-decimal-no-leading-zero", | ||
| "description": "Decimal without unnecessary leading zeros (1.23 is valid; 01.23 is invalid JSON syntax)", | ||
| "expected": "valid", | ||
| "value": 1.23 | ||
| } | ||
|
coderabbitai[bot] marked this conversation as resolved.
|
||
| ] | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| <?xml version="1.0" encoding="UTF-8"?> | ||
| <!-- | ||
| Invalid decimal test cases for XML validation. | ||
| Each test-case is in a separate file because invalid values cause validation to fail. | ||
| This file documents all invalid cases and their expected behavior. | ||
|
|
||
| Test files: | ||
| - xml-test-leading-plus.xml: +12.34 (INVALID - leading + not allowed) | ||
| - xml-test-leading-zero.xml: 01.23 (INVALID - leading zeros not allowed) | ||
| - xml-test-no-leading-digit.xml: .47 (INVALID - must have digit before decimal) | ||
| - xml-test-trailing-decimal.xml: 123. (INVALID - must have digit after decimal) | ||
| - xml-test-leading-whitespace.xml: " 12.34" (VALID due to xs:double whitespace collapse) | ||
|
|
||
| Note: Leading/trailing whitespace passes validation because xs:double | ||
| applies whitespace normalization before pattern matching. | ||
| --> | ||
| <decimal-tests xmlns="http://csrc.nist.gov/ns/metaschema/test/decimal" | ||
| xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
| xsi:schemaLocation="http://csrc.nist.gov/ns/metaschema/test/decimal decimal-test.xsd"> | ||
|
|
||
| <!-- This is a placeholder. See individual xml-test-*.xml files for actual invalid cases. --> | ||
| <test-case id="placeholder" description="Placeholder - see individual test files" expected="valid"> | ||
| <value>0</value> | ||
| </test-case> | ||
|
|
||
| </decimal-tests> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| <?xml version="1.0" encoding="UTF-8"?> | ||
| <decimal-tests xmlns="http://csrc.nist.gov/ns/metaschema/test/decimal" | ||
| xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
| xsi:schemaLocation="http://csrc.nist.gov/ns/metaschema/test/decimal decimal-test.xsd"> | ||
| <test-case id="xml-leading-plus" description="Leading plus sign (e.g., +12.34)" expected="invalid"> | ||
| <value>+12.34</value> | ||
| </test-case> | ||
| </decimal-tests> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| <?xml version="1.0" encoding="UTF-8"?> | ||
| <decimal-tests xmlns="http://csrc.nist.gov/ns/metaschema/test/decimal" | ||
| xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
| xsi:schemaLocation="http://csrc.nist.gov/ns/metaschema/test/decimal decimal-test.xsd"> | ||
| <test-case id="xml-leading-whitespace" description="Leading whitespace (passes due to xs:double whitespace collapse)" expected="valid"> | ||
| <value> 12.34</value> | ||
| </test-case> | ||
| </decimal-tests> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| <?xml version="1.0" encoding="UTF-8"?> | ||
| <decimal-tests xmlns="http://csrc.nist.gov/ns/metaschema/test/decimal" | ||
| xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
| xsi:schemaLocation="http://csrc.nist.gov/ns/metaschema/test/decimal decimal-test.xsd"> | ||
| <test-case id="xml-leading-zero" description="Leading zeros (e.g., 01.23)" expected="invalid"> | ||
| <value>01.23</value> | ||
| </test-case> | ||
| </decimal-tests> |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.