cercide / fastapi-xml

adds xml support to fastapi
MIT License
12 stars 2 forks source link

How to define element with multiple sub elements? #13

Open jakestrouse00 opened 1 day ago

jakestrouse00 commented 1 day ago

Hi,

I am trying to define an element that contains multiple sub-elements (some of the sub-elements also contain multiple sub-elements). The XML I am aiming for looks like this:

<Query latencySensitive="true">
  <Checkin>2017-06-07</Checkin>
  <Nights>5</Nights>
  <DeadlineMs>500</DeadlineMs>
  <PropertyList>
    <Property>8675309</Property>
  </PropertyList>
  <Context>
    <Occupancy>4</Occupancy>
    <OccupancyDetails>
      <NumAdults>2</NumAdults>
      <Children>
        <Child age="4"/>
        <Child age="12"/>
      </Children>
    </OccupancyDetails>
    <UserCountry>US</UserCountry>
    <UserDevice>mobile</UserDevice>
  </Context>
</Query>

This is currently what I have written, but when submitting a request I get a 400, Bad Request with the response: { "detail": "There was an error parsing the body" }

@dataclass
class Query:
    checkin: str = field(
        metadata={"examples": ["2025-08-10"], "name": "Checkin", "type": "Element"}
    )
    nights: int = field(metadata={"examples": [3], "name": "Nights", "type": "Element"})
    property_list: List[str] = field(
        metadata={
            "wrapper": "PropertyList",
            "name": "Property",
            "type": "Element",
            "examples": [["64a58668992086b9bb75d6fa"]],
        }
    )
# everything above this works, but context is breaking it
    context: List[int | str | str] = field(
         metadata={
             "wrapper": "Context",
             "type": "Elements",
             "name": "rere",
             "choices": (
                 {"name": "Occupancy", "type": "Element", "examples": [2]},
                 {"name": "UserCountry", "type": "Element", "examples": ["GB"]},
                 {"name": "UserDevice", "type": "Element", "examples": ["Desktop"]}
             )
         }
     )

Any help would be greatly appreciated

cercide commented 9 hours ago

Hey there,

I’ve briefly reviewed the code you provided, and there are a few points that need your attention.

Unknown XML Element

The code is referencing a tag named rere, which is not part of the given example.

Type Declaration Mismatch

The type for context is declared as List[int | str | str], but the actual sub-elements for each choice are of type Element. This discrepancy needs to be addressed.

If you’re still encountering issues after resolving the above, you may want to reconsider the object’s structure as described in the following point.

Confusing XML Structure

I found the contextual data challenging to follow. It seems that using a context object with optional attributes would provide guest information more intuitively, rather than relying on checking the object type. Why do I bring this up? First, determining what data was provided this way seems unconventional. And second, the main reason:

I hadn’t considered the option of wrapping the type Elements. It could work, but my original intention for the wrapper argument was to handle structures like this:

<Context>
  <rere>...</rere>
  <rere>...</rere>
  <rere>...</rere>
</Context>