Repository: brightway-lca/brightway2-io

Issue:
Extraction of CPC & HS2017 classifications fail
The fix for #282  does not seem to work. See the example below:

### setup
- OS: Ubuntu 24.04.1 LTS
- Python: 3.12.8
- bw2data version: (4, 3)
- bw2io version: 0.9.3

### description of the issue
- CPC classification is truncated and only the first digit seems extracted (tested with ecoinvent-3.9.1-cutoff and ecoinvent-3.10.1-cutoff)
- HS2017 failed to be extracted (ecoinvent-3.10.1-cutoff only)

#### ecoinvent-3.10.1-cutoff

```python
filename = "08203446-9eb0-579b-a2db-8efbc9f35a9f_2a1573b0-ab2e-4126-b931-a4c8b240a97c.spold"
database = "ecoinvent-3.10.1-cutoff"
node = bd.get_node(filename=filename, database=database)
print(node["name"])
print(node['location'])
print(node['code'])
print(node["classifications"])
```
returns
```
market for isohexane
GLO
d4fd2299216f2df9ead62b51afff2710
[('EcoSpold01Categories', 'chemicals/organics'),
 ('ISIC rev.4 ecoinvent', '2011:Manufacture of basic chemicals'),
 ('CPC', '3')]
```
expected results
```
market for isohexane
GLO
d4fd2299216f2df9ead62b51afff2710
[('EcoSpold01Categories', 'chemicals/organics'),
 ('ISIC rev.4 ecoinvent', '2011:Manufacture of basic chemicals'),
 ('CPC', '34110: Hydrocarbons and their halogenated, sulphonated, nitrated or nitrosated derivatives'),
 ('HS2017', '290290: Cyclic hydrocarbons; n.e.c. in heading no. 2902')]
```
since `08203446-9eb0-579b-a2db-8efbc9f35a9f_2a1573b0-ab2e-4126-b931-a4c8b240a97c.spold` contains the following:

```xml
    <activityDescription>
      ...
      <classification classificationId="7ac1cbc6-1385-4a68-8647-ed7aa78db201">
        <classificationSystem xml:lang="en">EcoSpold01Categories</classificationSystem>
        <classificationValue xml:lang="en">chemicals/organics</classificationValue>
      </classification>
      <classification classificationId="28f738cc-bb73-48f8-b633-f83fb9bc5ddc">
        <classificationSystem xml:lang="en">ISIC rev.4 ecoinvent</classificationSystem>
        <classificationValue xml:lang="en">2011:Manufacture of basic chemicals</classificationValue>
      </classification>
      ...
    </activityDescription>
    <flowData>
      <intermediateExchange>
        ...
        <classification classificationId="39b0f0ab-1a2f-401b-9f4d-6e39400760a4">
          <classificationSystem xml:lang="en">By-product classification</classificationSystem>
          <classificationValue xml:lang="en">allocatable product</classificationValue>
        </classification>
        <classification classificationId="f9c4918d-e5bd-4d4d-96d0-76cf1fc4d53c">
          <classificationSystem xml:lang="en">CPC</classificationSystem>
          <classificationValue xml:lang="en">34110: Hydrocarbons and their halogenated, sulphonated, nitrated or nitrosated derivatives</classificationValue>
        </classification>
        <classification classificationId="26a493dd-33e2-5789-aad3-1179ff0bf8ec">
          <classificationSystem xml:lang="en">HS2017</classificationSystem>
          <classificationValue xml:lang="en">290290: Cyclic hydrocarbons; n.e.c. in heading no. 2902</classificationValue>
        </classification>
        ...
      </intermediateExchange>
      ...
    </flowData>
```


#### ecoinvent-3.9.1-cutoff

```python
filename = "329fad9d-2c83-57b1-98f1-79c7faeb0f99_2a1573b0-ab2e-4126-b931-a4c8b240a97c.spold"
database = "ecoinvent-3.9.1-cutoff"
node = bd.get_node(filename=filename, database=database)
print(node["name"])
print(node['location'])
print(node['code'])
print(node["classifications"])
```
returns
```
market for isohexane
GLO
7f94506cf1198efdfbd069a26f8ce1c6
[('EcoSpold01Categories', 'chemicals/organics'),
 ('ISIC rev.4 ecoinvent', '2011:Manufacture of basic chemicals'),
 ('CPC', '3')]
```

expected results
```
market for isohexane
GLO
d4fd2299216f2df9ead62b51afff2710
[('EcoSpold01Categories', 'chemicals/organics'),
 ('ISIC rev.4 ecoinvent', '2011:Manufacture of basic chemicals'),
 ('CPC', '341: Basic organic chemicals')]
```
since `329fad9d-2c83-57b1-98f1-79c7faeb0f99_2a1573b0-ab2e-4126-b931-a4c8b240a97c.spold` contains the following:

```xml
    <activityDescription>
      ...
      <classification classificationId="7ac1cbc6-1385-4a68-8647-ed7aa78db201">
        <classificationSystem xml:lang="en">EcoSpold01Categories</classificationSystem>
        <classificationValue xml:lang="en">chemicals/organics</classificationValue>
      </classification>
      <classification classificationId="28f738cc-bb73-48f8-b633-f83fb9bc5ddc">
        <classificationSystem xml:lang="en">ISIC rev.4 ecoinvent</classificationSystem>
        <classificationValue xml:lang="en">2011:Manufacture of basic chemicals</classificationValue>
      </classification>
      ...
    </activityDescription>
    <flowData>
      <intermediateExchange>
        ...
        <classification classificationId="39b0f0ab-1a2f-401b-9f4d-6e39400760a4">
          <classificationSystem xml:lang="en">By-product classification</classificationSystem>
          <classificationValue xml:lang="en">allocatable product</classificationValue>
        </classification>
        <classification classificationId="3fab12aa-bf00-4458-a36a-af1fc0dea9b0">
          <classificationSystem xml:lang="en">CPC</classificationSystem>
          <classificationValue xml:lang="en">341: Basic organic chemicals</classificationValue>
        </classification>
        ...
      </intermediateExchange>
      ...
    </flowData>
```

#### additional comments

What puzzles me, is that a CPC value is extracted at all. If it had failed to extract anything all together, this could have been explained by the additional classifications (CPC and HS2017) being located in the `<flowData>` `<intermediateExchange>`.

Discussion hints:

Solution patch:
diff --git a/bw2io/strategies/ecospold2.py b/bw2io/strategies/ecospold2.py
index 4a4375d..f506849 100644
--- a/bw2io/strategies/ecospold2.py
+++ b/bw2io/strategies/ecospold2.py
@@ -1177,6 +1177,8 @@ def add_cpc_classification_from_single_reference_product(db):
             "classifications": [],
         }
 
+        The classifications dictionnary may have as values lists or single strings.
+
     Returns
     -------
     list
@@ -1221,9 +1223,11 @@ def add_cpc_classification_from_single_reference_product(db):
         assert "classifications" in ds
         products = [exc for exc in ds["exchanges"] if exc["type"] == "production"]
         if len(products) == 1 and has_cpc(products[0]):
-            ds["classifications"].append(
-                ("CPC", products[0]["classifications"]["CPC"][0])
-            )
+            if isinstance(products[0]["classifications"]["CPC"], list):
+                cpc_classif = products[0]["classifications"]["CPC"][0]
+            else:
+                cpc_classif = products[0]["classifications"]["CPC"]
+            ds["classifications"].append(("CPC", cpc_classif))
     return db
 
 


Test patch:
diff --git a/tests/strategies/ecospold2.py b/tests/strategies/ecospold2.py
index 22d05c4..7e27bc5 100644
--- a/tests/strategies/ecospold2.py
+++ b/tests/strategies/ecospold2.py
@@ -1,4 +1,4 @@
-from stats_arrays import *
+from stats_arrays import LognormalUncertainty, UndefinedUncertainty
 
 from bw2io.strategies.ecospold2 import (
     add_cpc_classification_from_single_reference_product,
@@ -303,6 +303,45 @@ def test_drop_temporary_outdated_biosphere_flows():
     assert (drop_temporary_outdated_biosphere_flows(given)) == expected
 
 
+def test_add_cpc_classification_from_single_reference_product_single_classif():
+    given = [
+        {
+            "classifications": [
+                ("EcoSpold01Categories", "hard coal/power plants"),
+                (
+                    "ISIC rev.4 ecoinvent",
+                    "3510:Electric power generation, transmission and distribution",
+                ),
+            ],
+            "exchanges": [
+                {
+                    "type": "production",
+                    "classifications": {"CPC": "17100: Electrical energy"},
+                }
+            ],
+        }
+    ]
+    expected = [
+        {
+            "classifications": [
+                ("EcoSpold01Categories", "hard coal/power plants"),
+                (
+                    "ISIC rev.4 ecoinvent",
+                    "3510:Electric power generation, transmission and distribution",
+                ),
+                ("CPC", "17100: Electrical energy"),
+            ],
+            "exchanges": [
+                {
+                    "type": "production",
+                    "classifications": {"CPC": "17100: Electrical energy"},
+                }
+            ],
+        }
+    ]
+    assert add_cpc_classification_from_single_reference_product(given) == expected
+
+
 def test_add_cpc_classification_from_single_reference_product():
     given = [
         {