Repository: tefra/xsdata

Issue:
xs:decimal improperly converted to scientific notation
xsdata version tested = 23.6
Python versions tested = 3.8, 3.9, 3.10, 3.11
----

When an XSD Element has type `xs:decimal` type
```xsd
<xs:element name="MyDecimal" type="xs:decimal">
```
and the input value is up to 6 decimal places
```xml
<MyDecimal>0.000000</MyDecimal>
<MyDecimal>0.000001</MyDecimal>
```
it parses and validates fine.

However, if the value is more than 6 decimal places and the first 6 are zeros
```xml
<MyDecimal>0.000000123456789</MyDecimal>
```
then validation fails because the value gets converted to scientific notation which is not allowed for `xs:decimal`
```log
xmlschema.validators.exceptions.XMLSchemaDecodeError: failed validating '1.23456789E-7' with XsdAtomicBuiltin(name='xs:decimal'):

Reason: invalid value '1.23456789E-7' for xs:decimal
```

If there is a non-zero number in one of the first places, then many places may be used and validate successfully
```xml
<MyDecimal>0.100000123456789</MyDecimal>
<MyDecimal>0.00000123456789</MyDecimal>
<MyDecimal>1.00000000000000</MyDecimal>
<MyDecimal>0.00000100000000</MyDecimal>
```

Discussion:
sonarcloud[bot]: Kudos, SonarCloud Quality Gate passed!&nbsp; &nbsp; [![Quality Gate passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/passed-16px.png 'Quality Gate passed')](https://sonarcloud.io/dashboard?id=tefra_xsdata&pullRequest=826)

[![Bug](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/bug-16px.png 'Bug')](https://sonarcloud.io/project/issues?id=tefra_xsdata&pullRequest=826&resolved=false&types=BUG) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=tefra_xsdata&pullRequest=826&resolved=false&types=BUG) [0 Bugs](https://sonarcloud.io/project/issues?id=tefra_xsdata&pullRequest=826&resolved=false&types=BUG)  
[![Vulnerability](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/vulnerability-16px.png 'Vulnerability')](https://sonarcloud.io/project/issues?id=tefra_xsdata&pullRequest=826&resolved=false&types=VULNERABILITY) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=tefra_xsdata&pullRequest=826&resolved=false&types=VULNERABILITY) [0 Vulnerabilities](https://sonarcloud.io/project/issues?id=tefra_xsdata&pullRequest=826&resolved=false&types=VULNERABILITY)  
[![Security Hotspot](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/security_hotspot-16px.png 'Security Hotspot')](https://sonarcloud.io/project/security_hotspots?id=tefra_xsdata&pullRequest=826&resolved=false&types=SECURITY_HOTSPOT) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/security_hotspots?id=tefra_xsdata&pullRequest=826&resolved=false&types=SECURITY_HOTSPOT) [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=tefra_xsdata&pullRequest=826&resolved=false&types=SECURITY_HOTSPOT)  
[![Code Smell](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/code_smell-16px.png 'Code Smell')](https://sonarcloud.io/project/issues?id=tefra_xsdata&pullRequest=826&resolved=false&types=CODE_SMELL) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=tefra_xsdata&pullRequest=826&resolved=false&types=CODE_SMELL) [0 Code Smells](https://sonarcloud.io/project/issues?id=tefra_xsdata&pullRequest=826&resolved=false&types=CODE_SMELL)

[![No Coverage information](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/CoverageChart/NoCoverageInfo-16px.png 'No Coverage information')](https://sonarcloud.io/component_measures?id=tefra_xsdata&pullRequest=826) No Coverage information  
[![0.0%](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/Duplications/3-16px.png '0.0%')](https://sonarcloud.io/component_measures?id=tefra_xsdata&pullRequest=826&metric=new_duplicated_lines_density&view=list) [0.0% Duplication](https://sonarcloud.io/component_measures?id=tefra_xsdata&pullRequest=826&metric=new_duplicated_lines_density&view=list)


codecov[bot]: ## [Codecov](https://app.codecov.io/gh/tefra/xsdata/pull/826?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Chris+Tsou) Report
Patch coverage: **`100.00`**% and no project coverage change.
> Comparison is base [(`d39e9aa`)](https://app.codecov.io/gh/tefra/xsdata/commit/d39e9aa62d72ef298915b00e8133a42dfaa1fe38?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Chris+Tsou) 99.96% compared to head [(`60a3a63`)](https://app.codecov.io/gh/tefra/xsdata/pull/826?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Chris+Tsou) 99.96%.

<details><summary>Additional details and impacted files</summary>


```diff
@@           Coverage Diff           @@
##             main     #826   +/-   ##
=======================================
  Coverage   99.96%   99.96%           
=======================================
  Files         104      104           
  Lines        9249     9249           
  Branches     2068     2068           
=======================================
  Hits         9246     9246           
  Partials        3        3           
```


| [Impacted Files](https://app.codecov.io/gh/tefra/xsdata/pull/826?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Chris+Tsou) | Coverage Δ | |
|---|---|---|
| [xsdata/formats/converter.py](https://app.codecov.io/gh/tefra/xsdata/pull/826?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Chris+Tsou#diff-eHNkYXRhL2Zvcm1hdHMvY29udmVydGVyLnB5) | `100.00% <100.00%> (ø)` | |


</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/tefra/xsdata/pull/826?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Chris+Tsou).   
:loudspeaker: Do you have feedback about the report comment? [Let us know in this issue](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Chris+Tsou).


Patch:
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index ffe4a731..c8a03150 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -2,7 +2,7 @@ exclude: tests/fixtures
 
 repos:
   - repo: https://github.com/asottile/pyupgrade
-    rev: v3.7.0
+    rev: v3.9.0
     hooks:
       - id: pyupgrade
         args: [ --py37-plus ]
@@ -11,11 +11,11 @@ repos:
     hooks:
       - id: reorder-python-imports
   - repo: https://github.com/ambv/black
-    rev: 23.3.0
+    rev: 23.7.0
     hooks:
       - id: black
   - repo: https://github.com/PyCQA/autoflake
-    rev: v2.1.1
+    rev: v2.2.0
     hooks:
       - id: autoflake
   - repo: https://github.com/PyCQA/flake8
@@ -41,7 +41,7 @@ repos:
       - id: docformatter
         args: [ "--in-place", "--pre-summary-newline" ]
   - repo: https://github.com/pre-commit/mirrors-mypy
-    rev: v1.4.0
+    rev: v1.4.1
     hooks:
       - id: mypy
         files: ^(xsdata/)
diff --git a/xsdata/formats/converter.py b/xsdata/formats/converter.py
index 1f0eb476..521fadd7 100644
--- a/xsdata/formats/converter.py
+++ b/xsdata/formats/converter.py
@@ -324,7 +324,7 @@ class DecimalConverter(Converter):
         if value.is_infinite():
             return str(value).replace("Infinity", "INF")
 
-        return str(value)
+        return f"{value:f}"
 
 
 class QNameConverter(Converter):


Test patch:
diff --git a/tests/formats/test_converter.py b/tests/formats/test_converter.py
index c4362cbc..0519ff50 100644
--- a/tests/formats/test_converter.py
+++ b/tests/formats/test_converter.py
@@ -42,7 +42,7 @@ class ConverterFactoryTests(TestCase):
         self.assertEqual("1.5", converter.serialize(1.5))
         self.assertEqual("true", converter.serialize(True))
         self.assertEqual("optional", converter.serialize(UseType.OPTIONAL))
-        self.assertEqual("8.77683E-8", converter.serialize(Decimal("8.77683E-8")))
+        self.assertEqual("0.0000000877683", converter.serialize(Decimal("8.77683E-8")))
         self.assertEqual("8.77683E-08", converter.serialize(float("8.77683E-8")))
 
     def test_test(self):
@@ -254,7 +254,9 @@ class DecimalConverterTests(TestCase):
         self.assertEqual("INF", self.converter.serialize(Decimal("inf")))
         self.assertEqual("INF", self.converter.serialize(Decimal("+inf")))
         self.assertEqual("-INF", self.converter.serialize(Decimal("-inf")))
-        self.assertEqual("8.77683E-8", self.converter.serialize(Decimal("8.77683E-8")))
+        self.assertEqual(
+            "0.0000000877683", self.converter.serialize(Decimal("8.77683E-8"))
+        )
 
 
 class DateTimeConverterTests(TestCase):