Skip to content
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

Unicode Characters Causing XML Data Error #715

Open
alroyer opened this issue Oct 26, 2024 · 1 comment
Open

Unicode Characters Causing XML Data Error #715

alroyer opened this issue Oct 26, 2024 · 1 comment

Comments

@alroyer
Copy link

alroyer commented Oct 26, 2024

In our application, we have products with metadata entered by our customers. Some of them need to input Unicode characters, often using the degree symbol (°).

However, when this symbol appears in the metadata value, we encounter the following error:

ValueError: All strings must be XML compatible: Unicode or ASCII, no NULL bytes or control characters.

Here is a snippet of code to reproduce this error:

from spyne import Application, ServiceBase, Unicode, rpc
from spyne.model.complex import Array, ComplexModel, XmlAttribute, XmlData
from spyne.protocol.http import HttpRpc
from spyne.protocol.soap import Soap11
from spyne.server.wsgi import WsgiApplication


class Metadata(ComplexModel):
    _type_info = [
        ("name", XmlAttribute(Unicode(sub_name="name"))),
        ("value", XmlData(Unicode(sub_name="value"))),
    ]


class Product(ComplexModel):
    _type_info = [
        ("metadata", Array(Metadata)),
    ]


class ProductService(ServiceBase):
    @rpc(_returns=Product)
    def get_product(ctx):
        product = Product()
        product.metadata = [
            Metadata(name="name", value="°"),
        ]
        return product


wsgi_app = WsgiApplication(
    Application(
        [ProductService],
        tns="spyne.examples",
        in_protocol=HttpRpc(validator="soft"),
        out_protocol=Soap11(),
    )
)
Python 3.10.15

Package    Version
---------- -------
gunicorn   23.0.0
lxml       5.3.0
packaging  24.1
pip        24.2
pytz       2024.2
setuptools 74.1.2
spyne      2.14.0
@alroyer
Copy link
Author

alroyer commented Oct 31, 2024

We found a workaround:

from spyne import Application, ServiceBase, Unicode, rpc
from spyne.model.complex import Array, ComplexModel, XmlAttribute, XmlData
from spyne.protocol.http import HttpRpc
from spyne.protocol.soap import Soap11
from spyne.server.wsgi import WsgiApplication


class MetadataValue(XmlData):
    @classmethod
    def marshall(cls, prot, name, value, parent_elt):
        if isinstance(value, str):
            parent_elt.text = value
        else:
            super().marshall(prot, name, value, parent_elt)


class Metadata(ComplexModel):
    _type_info = [
        ("name", XmlAttribute(Unicode(sub_name="name"))),
        ("value", MetadataValue(Unicode(sub_name="value"))),
    ]


class Product(ComplexModel):
    _type_info = [
        ("metadata", Array(Metadata)),
    ]


class ProductService(ServiceBase):
    @rpc(_returns=Product)
    def get_product(ctx):
        product = Product()
        product.metadata = [
            Metadata(name="name", value="value"),
            Metadata(name="name", value="<>{}&'\"°"),
        ]
        return product


wsgi_app = WsgiApplication(
    Application(
        [ProductService],
        tns="spyne.examples",
        in_protocol=HttpRpc(validator="soft"),
        out_protocol=Soap11(),
    )
)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant