Skip to content

Commit

Permalink
Merge pull request #8 from Tinny-Robot/main
Browse files Browse the repository at this point in the history
feat: Add functions for XML to JSON, JSON to XML, and XML to CSV conversion
  • Loading branch information
C-o-m-o-n committed Oct 27, 2023
2 parents 7ee0383 + 5b90557 commit 6e01194
Show file tree
Hide file tree
Showing 4 changed files with 167 additions and 8 deletions.
39 changes: 39 additions & 0 deletions .github/workflows/python-app.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# This workflow will install Python dependencies, run tests and lint with a single version of Python
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python

name: Python application

on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]

permissions:
contents: read

jobs:
build:

runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v3
- name: Set up Python 3.10
uses: actions/setup-python@v3
with:
python-version: "3.10"
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install flake8 pytest pylint
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
- name: Lint with flake8
run: |
# stop the build if there are Python syntax errors or undefined names
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
# exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
- name: Test with pytest
run: |
pylint --fail-under=7.8 textbin/textbin.py
18 changes: 16 additions & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,16 @@
# contributions
your contributions will be highly appreciated. I hope it be of help to you thank you. c-o-m-o-n
# Contributing

Thank you for considering contributing to our project! We welcome all contributions, big or small, and appreciate your time and effort.

To get started, please take a look at our [README.md](./README.md) file for an overview of the project and its goals. If you have any questions or need help with anything, please don't hesitate to reach out to us.

When submitting a contribution, please follow these guidelines:

- Make sure your code is well-documented and easy to understand.
- Write clear commit messages that describe the changes you've made.
- Test your code thoroughly to ensure it works as expected.
- Follow our code style and formatting guidelines.
- Be respectful and professional in all interactions with other contributors and maintainers.

Thank you again for your contributions, and we look forward to working with you!
@c-o-m-o-n
3 changes: 3 additions & 0 deletions examples.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
- base64_to_json: Converts a base64-encoded string to a JSON object.
- csv_to_json: Converts a CSV string to a JSON object.
- json_to_csv: Converts a JSON object to a CSV string.
- xml_to_json: Converts an XML string to a JSON object.
- json_to_xml: Converts a JSON object to an XML string.
- xml_to_csv: Converts an XML string to a CSV file.
-----
To begin, create an object from the Textbin() class, which you'll use to access all the methods.
Expand Down
115 changes: 109 additions & 6 deletions textbin/textbin.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,24 @@
import base64
from typing import Union
import csv
import xml.etree.ElementTree as ET

class Textbin:
"""
A class for converting between various text formats.
Methods:
- to_binary: Converts text to binary representation.
- to_text: Converts binary representation to text.
- json_to_base64: Converts a JSON object to a base64-encoded string.
- base64_to_json: Converts a base64-encoded string to a JSON object.
- xml_to_json: Converts an XML string to a JSON object.
- json_to_xml: Converts a JSON object to an XML string.
- xml_to_csv: Converts an XML string to a CSV file.
"""
def __init__(self):
pass

def to_binary(self, text: str) -> str:
"""Convert text to binary representation."""
binary = " ".join(format(ord(i), "b") for i in str(text))
Expand Down Expand Up @@ -121,17 +137,104 @@ def bin_to_json(self, binary: str) -> Union[dict, list]:
except Exception as e:
raise ValueError(f"Error converting binary to JSON: {e}")


def xml_to_json(self, xml_string: str) -> Union[dict, list]:
"""Convert an XML string to a JSON object."""
try:
root = ET.fromstring(xml_string)
json_data = self._element_to_dict(root)
return json_data
except ET.ParseError as e:
raise ValueError(f"Invalid XML data: {e}")
except Exception as e:
raise ValueError(f"Error converting from XML to JSON: {e}")

def json_to_xml(self, json_data: Union[dict, list]) -> str:
"""Convert a JSON object to an XML string."""
try:
root = self._dict_to_element(json_data)
xml_string = ET.tostring(root, encoding="unicode")
return xml_string
except Exception as e:
raise ValueError(f"Error converting from JSON to XML: {e}")

def xml_to_csv(self, xml_string: str, csv_file: str) -> None:
"""Convert an XML string to a CSV file."""
try:
root = ET.fromstring(xml_string)
with open(csv_file, "w", newline="", encoding="utf-8") as f:
writer = csv.writer(f)
header = []
for child in root:
row = []
for key, value in child.attrib.items():
if key not in header:
header.append(key)
row.append(value)
writer.writerow(row)
writer.writerow(header)
except ET.ParseError as e:
raise ValueError(f"Invalid XML data: {e}") from e
except Exception as e:
raise ValueError(f"Error converting from XML to CSV: {e}") from e


def _element_to_dict(self, element: ET.Element) -> Union[dict, list]:
"""Convert an ElementTree element to a dictionary."""
if element:
if element.attrib:
return {element.tag: element.attrib}
children = element.getchildren()
if children:
out = {}
for child in children:
result = self._element_to_dict(child)
if child.tag in out:
if isinstance(out[child.tag], list):
out[child.tag].append(result)
else:
out[child.tag] = [out[child.tag], result]
else:
out[child.tag] = result
return {element.tag: out}
return {element.tag: element.text}
return None

def _dict_to_element(self, data: Union[dict, list]) -> ET.Element:
"""Convert a dictionary to an ElementTree element."""
if isinstance(data, dict):
items = data.items()
elif isinstance(data, list):
items = enumerate(data)
else:
raise ValueError(f"Invalid data type: {type(data)}")
elem = ET.Element("item")
for key, value in items:
if isinstance(value, dict):
child = self._dict_to_element(value)
child.tag = key
elem.append(child)
elif isinstance(value, list):
for item in value:
child = self._dict_to_element(item)
child.tag = key
elem.append(child)
else:
child = ET.Element(key)
child.text = str(value)
elem.append(child)
return elem

if __name__ == "__main__":
textbin = Textbin()

textbin = Textbin()
word = {"foo": "bar"}

try:
converted_word = textbin.json_to_base64(word)
print(converted_word) # Output: eyJmb28iOiAiYmFyIn0=

base64_string = "eyJmb28iOiAiYmFyIn0="
converted_binary = textbin.base64_to_json(base64_string)
print(converted_word) # Output: eyJmb28iOiAiYmFyIn0=
BASE64_STRING = "eyJmb28iOiAiYmFyIn0="
converted_binary = textbin.base64_to_json(BASE64_STRING)
print(converted_binary) # Output: {'foo': 'bar'}

except ValueError as e:
print(f"Error: {e}")

0 comments on commit 6e01194

Please sign in to comment.