{"id":13469339,"url":"https://github.com/martinblech/xmltodict","last_synced_at":"2026-07-11T02:26:43.676Z","repository":{"id":3033084,"uuid":"4053456","full_name":"martinblech/xmltodict","owner":"martinblech","description":"Python module that makes working with XML feel like you are working with JSON","archived":false,"fork":false,"pushed_at":"2026-06-15T17:40:19.000Z","size":251,"stargazers_count":5744,"open_issues_count":3,"forks_count":473,"subscribers_count":98,"default_branch":"master","last_synced_at":"2026-07-09T16:44:35.200Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/martinblech.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null},"funding":{"github":["martinblech"]}},"created_at":"2012-04-17T14:38:21.000Z","updated_at":"2026-07-08T19:03:59.000Z","dependencies_parsed_at":"2026-03-11T09:01:34.522Z","dependency_job_id":"59e1a82d-4342-4668-91a1-404114a057e0","html_url":"https://github.com/martinblech/xmltodict","commit_stats":{"total_commits":217,"total_committers":53,"mean_commits":4.09433962264151,"dds":0.5069124423963134,"last_synced_commit":"0952f382c2340bc8b86a5503ba765a35a49cf7c4"},"previous_names":[],"tags_count":40,"template":false,"template_full_name":null,"purl":"pkg:github/martinblech/xmltodict","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/martinblech%2Fxmltodict","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/martinblech%2Fxmltodict/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/martinblech%2Fxmltodict/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/martinblech%2Fxmltodict/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/martinblech","download_url":"https://codeload.github.com/martinblech/xmltodict/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/martinblech%2Fxmltodict/sbom","scorecard":{"id":621550,"data":{"date":"2025-08-11","repo":{"name":"github.com/martinblech/xmltodict","commit":"0952f382c2340bc8b86a5503ba765a35a49cf7c4"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":4.3,"checks":[{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/test.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Code-Review","score":3,"reason":"Found 10/26 approved changesets -- score normalized to 3","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/test.yml:15: update your workflow using https://app.stepsecurity.io/secureworkflow/martinblech/xmltodict/test.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/test.yml:17: update your workflow using https://app.stepsecurity.io/secureworkflow/martinblech/xmltodict/test.yml/master?enable=pin","Warn: pipCommand not pinned by hash: .github/workflows/test.yml:22","Warn: pipCommand not pinned by hash: .github/workflows/test.yml:23","Info:   0 out of   2 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   2 pipCommand dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":10,"reason":"project is fuzzed","details":["Info: OSSFuzz integration found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 16 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-21T05:20:27.929Z","repository_id":3033084,"created_at":"2025-08-21T05:20:27.930Z","updated_at":"2025-08-21T05:20:27.930Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35335897,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-10T02:00:06.465Z","response_time":60,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-07-31T15:01:34.613Z","updated_at":"2026-07-11T02:26:43.645Z","avatar_url":"https://github.com/martinblech.png","language":"Python","funding_links":["https://github.com/sponsors/martinblech"],"categories":["HTML Manipulation","Python","资源列表","Data Loading \u0026 Extraction","Uncategorized","HTML 处理","Data Format \u0026 I/O","HTML操作","HarmonyOS","数据读写与提取","HTML Manipulation [🔝](#readme)","Specialized Tools","Awesome Python","📦 Additional Python Libraries","Libraries","1.0 Software Development and Design (15%)"],"sub_categories":["HTML 处理","Uncategorized","For Python","Windows Manager","Libraries","Python libraries","HTML/XML Processing","HTML Manipulation","Documentation \u0026 File Processing","JSON and Data Parsing","Resources"],"readme":"# xmltodict\n\n`xmltodict` is a Python module that makes working with XML feel like you are working with [JSON](http://docs.python.org/library/json.html), as in this [\"spec\"](http://www.xml.com/pub/a/2006/05/31/converting-between-xml-and-json.html):\n\n[![Build Status](https://app.travis-ci.com/martinblech/xmltodict.svg?branch=master)](https://app.travis-ci.com/martinblech/xmltodict)\n\n```python\n\u003e\u003e\u003e print(json.dumps(xmltodict.parse(\"\"\"\n...  \u003cmydocument has=\"an attribute\"\u003e\n...    \u003cand\u003e\n...      \u003cmany\u003eelements\u003c/many\u003e\n...      \u003cmany\u003emore elements\u003c/many\u003e\n...    \u003c/and\u003e\n...    \u003cplus a=\"complex\"\u003e\n...      element as well\n...    \u003c/plus\u003e\n...  \u003c/mydocument\u003e\n...  \"\"\"), indent=4))\n{\n    \"mydocument\": {\n        \"@has\": \"an attribute\", \n        \"and\": {\n            \"many\": [\n                \"elements\", \n                \"more elements\"\n            ]\n        }, \n        \"plus\": {\n            \"@a\": \"complex\", \n            \"#text\": \"element as well\"\n        }\n    }\n}\n```\n\n## Namespace support\n\nBy default, `xmltodict` does no XML namespace processing (it just treats namespace declarations as regular node attributes), but passing `process_namespaces=True` will make it expand namespaces for you:\n\n```python\n\u003e\u003e\u003e xml = \"\"\"\n... \u003croot xmlns=\"http://defaultns.com/\"\n...       xmlns:a=\"http://a.com/\"\n...       xmlns:b=\"http://b.com/\"\u003e\n...   \u003cx\u003e1\u003c/x\u003e\n...   \u003ca:y\u003e2\u003c/a:y\u003e\n...   \u003cb:z\u003e3\u003c/b:z\u003e\n... \u003c/root\u003e\n... \"\"\"\n\u003e\u003e\u003e xmltodict.parse(xml, process_namespaces=True) == {\n...     'http://defaultns.com/:root': {\n...         'http://defaultns.com/:x': '1',\n...         'http://a.com/:y': '2',\n...         'http://b.com/:z': '3',\n...     }\n... }\nTrue\n```\n\nIt also lets you collapse certain namespaces to shorthand prefixes, or skip them altogether:\n\n```python\n\u003e\u003e\u003e namespaces = {\n...     'http://defaultns.com/': None, # skip this namespace\n...     'http://a.com/': 'ns_a', # collapse \"http://a.com/\" -\u003e \"ns_a\"\n... }\n\u003e\u003e\u003e xmltodict.parse(xml, process_namespaces=True, namespaces=namespaces) == {\n...     'root': {\n...         'x': '1',\n...         'ns_a:y': '2',\n...         'http://b.com/:z': '3',\n...     },\n... }\nTrue\n```\n\n## Streaming mode\n\n`xmltodict` is very fast ([Expat](http://docs.python.org/library/pyexpat.html)-based) and has a streaming mode with a small memory footprint, suitable for big XML dumps like [Discogs](http://discogs.com/data/) or [Wikipedia](http://dumps.wikimedia.org/):\n\n```python\n\u003e\u003e\u003e def handle_artist(_, artist):\n...     print(artist['name'])\n...     return True\n\u003e\u003e\u003e \n\u003e\u003e\u003e xmltodict.parse(GzipFile('discogs_artists.xml.gz'),\n...     item_depth=2, item_callback=handle_artist)\nA Perfect Circle\nFantômas\nKing Crimson\nChris Potter\n...\n```\n\nIt can also be used from the command line to pipe objects to a script like this:\n\n```python\nimport sys, marshal\nwhile True:\n    _, article = marshal.load(sys.stdin)\n    print(article['title'])\n```\n\n```sh\n$ bunzip2 enwiki-pages-articles.xml.bz2 | xmltodict.py 2 | myscript.py\nAccessibleComputing\nAnarchism\nAfghanistanHistory\nAfghanistanGeography\nAfghanistanPeople\nAfghanistanCommunications\nAutism\n...\n```\n\nOr just cache the dicts so you don't have to parse that big XML file again. You do this only once:\n\n```sh\n$ bunzip2 enwiki-pages-articles.xml.bz2 | xmltodict.py 2 | gzip \u003e enwiki.dicts.gz\n```\n\nAnd you reuse the dicts with every script that needs them:\n\n```sh\n$ gunzip enwiki.dicts.gz | script1.py\n$ gunzip enwiki.dicts.gz | script2.py\n...\n```\n\n## Roundtripping\n\nYou can also convert in the other direction, using the `unparse()` method:\n\n```python\n\u003e\u003e\u003e mydict = {\n...     'response': {\n...             'status': 'good',\n...             'last_updated': '2014-02-16T23:10:12Z',\n...     }\n... }\n\u003e\u003e\u003e print(unparse(mydict, pretty=True))\n\u003c?xml version=\"1.0\" encoding=\"utf-8\"?\u003e\n\u003cresponse\u003e\n\t\u003cstatus\u003egood\u003c/status\u003e\n\t\u003clast_updated\u003e2014-02-16T23:10:12Z\u003c/last_updated\u003e\n\u003c/response\u003e\n```\n\nText values for nodes can be specified with the `cdata_key` key in the python dict, while node properties can be specified with the `attr_prefix` prefixed to the key name in the python dict. The default value for `attr_prefix` is `@` and the default value for `cdata_key` is `#text`.\n\n```python\n\u003e\u003e\u003e import xmltodict\n\u003e\u003e\u003e \n\u003e\u003e\u003e mydict = {\n...     'text': {\n...         '@color':'red',\n...         '@stroke':'2',\n...         '#text':'This is a test'\n...     }\n... }\n\u003e\u003e\u003e print(xmltodict.unparse(mydict, pretty=True))\n\u003c?xml version=\"1.0\" encoding=\"utf-8\"?\u003e\n\u003ctext stroke=\"2\" color=\"red\"\u003eThis is a test\u003c/text\u003e\n```\n\nLists that are specified under a key in a dictionary use the key as a tag for each item. But if a list does have a parent key, for example if a list exists inside another list, it does not have a tag to use and the items are converted to a string as shown in the example below.  To give tags to nested lists, use the `expand_iter` keyword argument to provide a tag as demonstrated below. Note that using `expand_iter` will break roundtripping.\n\n```python\n\u003e\u003e\u003e mydict = {\n...     \"line\": {\n...         \"points\": [\n...             [1, 5],\n...             [2, 6],\n...         ]\n...     }\n... }\n\u003e\u003e\u003e print(xmltodict.unparse(mydict, pretty=True))\n\u003c?xml version=\"1.0\" encoding=\"utf-8\"?\u003e\n\u003cline\u003e\n        \u003cpoints\u003e[1, 5]\u003c/points\u003e\n        \u003cpoints\u003e[2, 6]\u003c/points\u003e\n\u003c/line\u003e\n\u003e\u003e\u003e print(xmltodict.unparse(mydict, pretty=True, expand_iter=\"coord\"))\n\u003c?xml version=\"1.0\" encoding=\"utf-8\"?\u003e\n\u003cline\u003e\n        \u003cpoints\u003e\n                \u003ccoord\u003e1\u003c/coord\u003e\n                \u003ccoord\u003e5\u003c/coord\u003e\n        \u003c/points\u003e\n        \u003cpoints\u003e\n                \u003ccoord\u003e2\u003c/coord\u003e\n                \u003ccoord\u003e6\u003c/coord\u003e\n        \u003c/points\u003e\n\u003c/line\u003e\n```\n\n## Ok, how do I get it?\n\n### Using pypi\n\nYou just need to\n\n```sh\n$ pip install xmltodict\n```\n\n### Using conda\n\nFor installing `xmltodict` using Anaconda/Miniconda (*conda*) from the \n[conda-forge channel][#xmltodict-conda] all you need to do is:\n\n[#xmltodict-conda]: https://anaconda.org/conda-forge/xmltodict\n\n```sh\n$ conda install -c conda-forge xmltodict\n```\n\n### RPM-based distro (Fedora, RHEL, …)\n\nThere is an [official Fedora package for xmltodict](https://apps.fedoraproject.org/packages/python-xmltodict).\n\n```sh\n$ sudo yum install python-xmltodict\n```\n\n### Arch Linux\n\nThere is an [official Arch Linux package for xmltodict](https://www.archlinux.org/packages/community/any/python-xmltodict/).\n\n```sh\n$ sudo pacman -S python-xmltodict\n```\n\n### Debian-based distro (Debian, Ubuntu, …)\n\nThere is an [official Debian package for xmltodict](https://tracker.debian.org/pkg/python-xmltodict).\n\n```sh\n$ sudo apt install python-xmltodict\n```\n\n### FreeBSD\n\nThere is an [official FreeBSD port for xmltodict](https://svnweb.freebsd.org/ports/head/devel/py-xmltodict/).\n\n```sh\n$ pkg install py36-xmltodict\n```\n\n### openSUSE/SLE (SLE 15, Leap 15, Tumbleweed)\n\nThere is an [official openSUSE package for xmltodict](https://software.opensuse.org/package/python-xmltodict).\n\n```sh\n# Python2\n$ zypper in python2-xmltodict\n\n# Python3\n$ zypper in python3-xmltodict\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmartinblech%2Fxmltodict","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmartinblech%2Fxmltodict","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmartinblech%2Fxmltodict/lists"}