xsdata icon indicating copy to clipboard operation
xsdata copied to clipboard

Wrapping a list of element and primitive nodes

Open cercide opened this issue 3 years ago • 2 comments

📒 Description

XML data structures commonly wrap element and primitive collections. For instance, a library may have several books and and other stuff as well. In terms of OpenAPI 3, these data structures are wrapped. Hence, this PR introduces the field parameter wrapper, which wraps any element/primitive collection into a custom xml element without the need of a dedicated wrapper class.

from dataclasses import dataclass, field
from typing import List
from xsdata.formats.dataclass.serializers import XmlSerializer
from xsdata.formats.dataclass.serializers.config import SerializerConfig

config = SerializerConfig(pretty_print=True, xml_declaration=False)
serializer = XmlSerializer(config=config)

@dataclass
class Library:
    books: List[str] = field(
        metadata={
            "wrapper": "Books",
            "name": "Title",
            "type": "Element",
        }
    )

obj = Library(
    books = [
        "python for beginners",
        "beautiful xml",
    ]
)

print(serializer.render(obj))
<Library>
  <Books>
    <Title>python for beginners</Title>
    <Title>beautiful xml</Title>
  </Books>
</Library>

Resolves #709

🔗 What I've Done

First, a new metadata attribute wrapper indicates that a list is wrapped by an xml object.

Next, when the serializer writes a list, the wrapper attribute triggers XmlWriterEvent.START end before the serializer writes the list. Afterwards, an XmlWriterEvent.END event follows vice versa .

Finally, the parser introduces the class WrapperNode as a subclass of XmlNode. The WrapperNode class is a wrapper for the parent element and lines up into the node queue.

💬 Comments

This is a great library to work in pythonik way with xml. Thank you for your efforts!

🛫 Checklist

cercide avatar Sep 14 '22 19:09 cercide

Codecov Report

Base: 100.00% // Head: 100.00% // No change to project coverage :thumbsup:

Coverage data is based on head (0e84311) compared to base (a93f186). Patch coverage: 100.00% of modified lines in pull request are covered.

Additional details and impacted files
@@            Coverage Diff            @@
##            master      #710   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files          100       101    +1     
  Lines         8741      8776   +35     
  Branches      2212      2220    +8     
=========================================
+ Hits          8741      8776   +35     
Impacted Files Coverage Δ
xsdata/utils/testing.py 100.00% <ø> (ø)
xsdata/formats/dataclass/context.py 100.00% <100.00%> (ø)
xsdata/formats/dataclass/models/builders.py 100.00% <100.00%> (ø)
xsdata/formats/dataclass/models/elements.py 100.00% <100.00%> (ø)
xsdata/formats/dataclass/parsers/bases.py 100.00% <100.00%> (ø)
xsdata/formats/dataclass/parsers/nodes/__init__.py 100.00% <100.00%> (ø)
xsdata/formats/dataclass/parsers/nodes/wrapper.py 100.00% <100.00%> (ø)
xsdata/formats/dataclass/serializers/xml.py 100.00% <100.00%> (ø)

Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here.

:umbrella: View full report at Codecov.
:loudspeaker: Do you have feedback about the report comment? Let us know in this issue.

codecov[bot] avatar Sep 21 '22 13:09 codecov[bot]

Kudos, SonarCloud Quality Gate passed!    Quality Gate passed

Bug A 0 Bugs
Vulnerability A 0 Vulnerabilities
Security Hotspot A 0 Security Hotspots
Code Smell A 0 Code Smells

No Coverage information No Coverage information
No Duplication information No Duplication information

sonarqubecloud[bot] avatar Sep 26 '22 08:09 sonarqubecloud[bot]

Thank you for the contribution @cercide this is something I wanted to tackle at some point!!!

tefra avatar Sep 28 '22 08:09 tefra