{"id":32174842,"url":"https://github.com/weiwei/junitparser","last_synced_at":"2026-02-21T15:05:55.510Z","repository":{"id":37866131,"uuid":"71689841","full_name":"weiwei/junitparser","owner":"weiwei","description":"Parses JUnit/xUnit Result XML files with ease","archived":false,"fork":false,"pushed_at":"2025-10-16T00:49:14.000Z","size":273,"stargazers_count":134,"open_issues_count":6,"forks_count":53,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-10-29T17:39:34.914Z","etag":null,"topics":["junit","testing","testing-tools","xml"],"latest_commit_sha":null,"homepage":"https://junitparser.readthedocs.io","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/weiwei.png","metadata":{"files":{"readme":"README.rst","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2016-10-23T08:08:34.000Z","updated_at":"2025-10-16T00:49:19.000Z","dependencies_parsed_at":"2023-12-26T02:26:05.492Z","dependency_job_id":"302f417d-e9ae-4c26-aad8-537caee837fe","html_url":"https://github.com/weiwei/junitparser","commit_stats":{"total_commits":157,"total_committers":28,"mean_commits":5.607142857142857,"dds":0.6560509554140128,"last_synced_commit":"56480050fdc487590386909eec8d37af2c4497c8"},"previous_names":[],"tags_count":46,"template":false,"template_full_name":null,"purl":"pkg:github/weiwei/junitparser","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/weiwei%2Fjunitparser","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/weiwei%2Fjunitparser/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/weiwei%2Fjunitparser/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/weiwei%2Fjunitparser/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/weiwei","download_url":"https://codeload.github.com/weiwei/junitparser/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/weiwei%2Fjunitparser/sbom","scorecard":{"id":1238852,"data":{"date":"2025-10-06","repo":{"name":"github.com/weiwei/junitparser","commit":"689f9e1f1d9c4ca22ad62a07b5c24ca3718152cf"},"scorecard":{"version":"v5.3.1-0.20251003215448-f542d69ba0cd","commit":"f542d69ba0cd01fcff1cc4395b9780f2476af14d"},"score":4.2,"checks":[{"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/f542d69ba0cd01fcff1cc4395b9780f2476af14d/docs/checks.md#dangerous-workflow"}},{"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/f542d69ba0cd01fcff1cc4395b9780f2476af14d/docs/checks.md#binary-artifacts"}},{"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/f542d69ba0cd01fcff1cc4395b9780f2476af14d/docs/checks.md#maintained"}},{"name":"Code-Review","score":5,"reason":"Found 16/27 approved changesets -- score normalized to 5","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/f542d69ba0cd01fcff1cc4395b9780f2476af14d/docs/checks.md#code-review"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Info: Possibly incomplete results: error parsing job operating system: .github/workflows/test-os.yml:33","Info: Possibly incomplete results: error parsing job operating system: .github/workflows/test-os.yml:44","Info: Possibly incomplete results: error parsing job operating system: .github/workflows/test-os.yml:47","Info: Possibly incomplete results: error parsing job operating system: .github/workflows/test-whl.yml:37","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:152: update your workflow using https://app.stepsecurity.io/secureworkflow/weiwei/junitparser/ci.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:154: update your workflow using https://app.stepsecurity.io/secureworkflow/weiwei/junitparser/ci.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/ci.yml:163: update your workflow using https://app.stepsecurity.io/secureworkflow/weiwei/junitparser/ci.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:18: update your workflow using https://app.stepsecurity.io/secureworkflow/weiwei/junitparser/ci.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:71: update your workflow using https://app.stepsecurity.io/secureworkflow/weiwei/junitparser/ci.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:73: update your workflow using https://app.stepsecurity.io/secureworkflow/weiwei/junitparser/ci.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:99: update your workflow using https://app.stepsecurity.io/secureworkflow/weiwei/junitparser/ci.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:101: update your workflow using https://app.stepsecurity.io/secureworkflow/weiwei/junitparser/ci.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:128: update your workflow using https://app.stepsecurity.io/secureworkflow/weiwei/junitparser/ci.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/test-os.yml:28: update your workflow using https://app.stepsecurity.io/secureworkflow/weiwei/junitparser/test-os.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/test-os.yml:30: update your workflow using https://app.stepsecurity.io/secureworkflow/weiwei/junitparser/test-os.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/test-os.yml:53: update your workflow using https://app.stepsecurity.io/secureworkflow/weiwei/junitparser/test-os.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/test-results.yml:29: update your workflow using https://app.stepsecurity.io/secureworkflow/weiwei/junitparser/test-results.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/test-whl.yml:29: update your workflow using https://app.stepsecurity.io/secureworkflow/weiwei/junitparser/test-whl.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/test-whl.yml:33: update your workflow using https://app.stepsecurity.io/secureworkflow/weiwei/junitparser/test-whl.yml/master?enable=pin","Warn: pipCommand not pinned by hash: .github/workflows/ci.yml:108","Warn: pipCommand not pinned by hash: .github/workflows/ci.yml:83","Warn: pipCommand not pinned by hash: .github/workflows/ci.yml:84","Warn: downloadThenRun not pinned by hash: .github/workflows/ci.yml:92","Warn: pipCommand not pinned by hash: .github/workflows/test-os.yml:41","Warn: pipCommand not pinned by hash: .github/workflows/test-os.yml:42","Info:   0 out of  13 GitHub-owned GitHubAction dependencies pinned","Info:   1 out of   3 third-party GitHubAction dependencies pinned","Info:   0 out of   5 pipCommand dependencies pinned","Info:   0 out of   1 downloadThenRun 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/f542d69ba0cd01fcff1cc4395b9780f2476af14d/docs/checks.md#pinned-dependencies"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: jobLevel 'checks' permission set to 'write': .github/workflows/test-results.yml:17","Info: jobLevel 'actions' permission set to 'read': .github/workflows/test-results.yml:19","Warn: no topLevel permission defined: .github/workflows/ci.yml:1","Warn: no topLevel permission defined: .github/workflows/test-os.yml:1","Info: found token with 'none' permissions: .github/workflows/test-results.yml:1","Warn: no topLevel permission defined: .github/workflows/test-whl.yml:1"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f542d69ba0cd01fcff1cc4395b9780f2476af14d/docs/checks.md#token-permissions"}},{"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/f542d69ba0cd01fcff1cc4395b9780f2476af14d/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/f542d69ba0cd01fcff1cc4395b9780f2476af14d/docs/checks.md#security-policy"}},{"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/f542d69ba0cd01fcff1cc4395b9780f2476af14d/docs/checks.md#vulnerabilities"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f542d69ba0cd01fcff1cc4395b9780f2476af14d/docs/checks.md#fuzzing"}},{"name":"License","score":9,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Warn: project license file does not contain an FSF or OSI license."],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f542d69ba0cd01fcff1cc4395b9780f2476af14d/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/f542d69ba0cd01fcff1cc4395b9780f2476af14d/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/f542d69ba0cd01fcff1cc4395b9780f2476af14d/docs/checks.md#branch-protection"}},{"name":"Packaging","score":10,"reason":"packaging workflow detected","details":["Info: Project packages its releases by way of GitHub Actions.: .github/workflows/ci.yml:147"],"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/f542d69ba0cd01fcff1cc4395b9780f2476af14d/docs/checks.md#packaging"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 25 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f542d69ba0cd01fcff1cc4395b9780f2476af14d/docs/checks.md#sast"}}]},"last_synced_at":"2025-10-17T23:04:21.238Z","repository_id":37866131,"created_at":"2025-10-17T23:04:21.251Z","updated_at":"2025-10-17T23:04:21.251Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29684085,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-21T14:31:22.911Z","status":"ssl_error","status_checked_at":"2026-02-21T14:31:22.570Z","response_time":107,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["junit","testing","testing-tools","xml"],"created_at":"2025-10-21T19:11:56.747Z","updated_at":"2026-02-21T15:05:55.505Z","avatar_url":"https://github.com/weiwei.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"junitparser -- Pythonic JUnit/xUnit Result XML Parser\n======================================================\n\n.. image:: https://github.com/weiwei/junitparser/actions/workflows/ci.yml/badge.svg?branch=master\n   :target: https://github.com/weiwei/junitparser/actions\n.. image:: https://codecov.io/gh/weiwei/junitparser/branch/master/graph/badge.svg?token=UotlfRXNnK\n   :target: https://codecov.io/gh/weiwei/junitparser\n\njunitparser handles JUnit/xUnit Result XML files. Use it to parse and manipulate\nexisting Result XML files, or create new JUnit/xUnit result XMLs from scratch.\n\nFeatures\n--------\n\n* Parse or modify existing JUnit/xUnit XML files.\n* Parse or modify non-standard or customized JUnit/xUnit XML files, by monkey\n  patching existing element definitions.\n* Create JUnit/xUnit test results from scratch.\n* Merge test result XML files.\n* Specify XML parser. For example you can use lxml to speed things up.\n* Invoke from command line, or `python -m junitparser`\n* Python 2 and 3 support (As of Nov 2020, 1/4 of the users are still on Python\n  2, so there is no plan to drop Python 2 support)\n\nNote on version 2\n-----------------\n\nVersion 2 improved support for pytest result XML files by fixing a few issues,\nnotably that there could be multiple \u003cFailure\u003e or \u003cError\u003e entries. There is a\nbreaking change that ``TestCase.result`` is now a list instead of a single item.\nIf you are using this attribute, please update your code accordingly.\n\nInstallation\n-------------\n\n::\n\n    pip install junitparser\n\nUsage\n-----\n\nYou should be relatively familiar with the Junit XML format. If not, run\n``pydoc`` on the exposed classes and functions to see how it's structured.\n\nCreate Junit XML format reports from scratch\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nYou have some test result data, and you want to convert them into junit.xml\nformat.\n\n.. code-block:: python\n\n    from junitparser import TestCase, TestSuite, JUnitXml, Skipped, Error\n\n    # Create cases\n    case1 = TestCase('case1', 'class.name', 0.5) # params are optional\n    case1.classname = \"modified.class.name\" # specify or change case attrs\n    case1.result = [Skipped()] # You can have a list of results\n    case2 = TestCase('case2')\n    case2.result = [Error('Example error message', 'the_error_type')]\n\n    # Create suite and add cases\n    suite = TestSuite('suite1')\n    suite.add_property('build', '55')\n    suite.add_testcase(case1)\n    suite.add_testcase(case2)\n    suite.remove_testcase(case2)\n\n    #Bulk add cases to suite\n    case3 = TestCase('case3')\n    case4 = TestCase('case4')\n    suite.add_testcases([case3, case4])\n\n    # Add suite to JunitXml\n    xml = JUnitXml()\n    xml.add_testsuite(suite)\n    xml.write('junit.xml')\n\nRead and manipulate existing JUnit/xUnit XML files\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nYou have some existing junit.xml files, and you want to modify the content.\n\n.. code-block:: python\n\n    from junitparser import JUnitXml\n\n    xml = JUnitXml.fromfile('/path/to/junit.xml')\n    for suite in xml:\n        # handle suites\n        for case in suite:\n            # handle cases\n    xml.write() # Writes back to file\n\nIt is also possible to use a custom parser. For example lxml provides a plethora\nof parsing options_. We can use them this way:\n\n.. code-block:: python\n\n    from lxml.etree import XMLParser, parse\n    from junitparser import JUnitXml\n\n    def parse_func(file_path):\n        xml_parser = XMLParser(huge_tree=True)\n        return parse(file_path, xml_parser)\n\n    xml = JUnitXml.fromfile('/path/to/junit.xml', parse_func)\n    # process xml...\n\n.. _options: https://lxml.de/api/lxml.etree.XMLParser-class.html\n\nMerge XML files\n~~~~~~~~~~~~~~~\n\nYou have two or more XML files, and you want to merge them into one.\n\n.. code-block:: python\n\n    from junitparser import JUnitXml\n\n    xml1 = JUnitXml.fromfile('/path/to/junit1.xml')\n    xml2 = JUnitXml.fromfile('/path/to/junit2.xml')\n\n    newxml = xml1 + xml2\n    # Alternatively, merge in place\n    xml1 += xml2\n\nNote that it won't check for duplicate entries. You need to deal with them on\nyour own.\n\nSchema Support\n~~~~~~~~~~~~~~~\n\nBy default junitparser supports the schema of windyroad_, which is a relatively\nsimple schema.\n\n.. _windyroad: https://github.com/windyroad/JUnit-Schema/blob/master/JUnit.xsd\n\nJunitparser also support extra schemas:\n\n.. code-block:: python\n\n    from junitparser.xunit2 import TestCase, TestSuite, RerunFailure\n    # These classes are redefined to support extra properties and attributes\n    # of the xunit2 schema.\n    suite = TestSuite(\"mySuite\")\n    suite.system_err = \"System err\" # xunit2 specific property\n    case = TestCase(\"myCase\")\n    rerun_failure = RerunFailure(\"Not found\", \"404\") # case property\n    rerun_failure.stack_trace = \"Stack\"\n    rerun_failure.system_err = \"E404\"\n    rerun_failure.system_out = \"NOT FOUND\"\n    case.add_interim_result(rerun_failure)\n\nCurrently supported schemas including:\n\n- xunit2_, supported by pytest, Erlang/OTP, Maven Surefire, CppTest, etc.\n\n.. _xunit2: https://github.com/jenkinsci/xunit-plugin/blob/xunit-2.3.2/src/main/resources/org/jenkinsci/plugins/xunit/types/model/xsd/junit-10.xsd\n\nPRs are welcome to support more schemas.\n\nCreate XML with custom attributes\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nYou want to use an attribute that is not supported by default.\n\n.. code-block:: python\n\n    from junitparser import TestCase, Attr, IntAttr, FloatAttr\n\n    # Add the custom attribute\n    TestCase.id = IntAttr('id')\n    TestCase.rate = FloatAttr('rate')\n    TestCase.custom = Attr('custom')\n    case = TestCase()\n    case.id = 123\n    case.rate = 0.95\n    case.custom = 'foobar'\n\n\nHandling XML with custom element\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nThere may be once in 1000 years you want to it this way, but anyways.\nSuppose you want to add element CustomElement to TestCase.\n\n.. code-block:: python\n\n    from junitparser import Element, Attr, TestSuite\n\n    # Create the new element by subclassing Element,\n    # and add custom attributes to it.\n    class CustomElement(Element):\n        _tag = 'custom'\n        foo = Attr()\n        bar = Attr()\n\n    testcase = TestCase()\n    custom = CustomElement()\n    testcase.append(custom)\n    # To find a single sub-element:\n    testcase.child(CustomElement)\n    # To iterate over custom elements:\n    for custom in testcase.iterchildren(CustomElement):\n        ... # Do things with custom element\n\nHandling custom XML attributes\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nSay you have some data stored in the XML as custom attributes and you want to\nread them out:\n\n.. code-block:: python\n\n    from junitparser import TestCase, Attr, JUnitXml\n\n    # Create the new element by subclassing Element or one of its child class,\n    # and add custom attributes to it.\n    class MyTestCase(TestCase):\n        foo = Attr()\n\n    xml = JUnitXml.fromfile('/path/to/junit.xml')\n    for suite in xml:\n        # handle suites\n        for case in suite:\n            my_case = MyTestCase.fromelem(case)\n            print(my_case.foo)\n\nCommand Line\n------------\n\n.. code-block:: console\n\n    $ junitparser --help\n    usage: junitparser [-h] [-v] {merge} ...\n\n    Junitparser CLI helper.\n\n    positional arguments:\n    {merge}        command\n      merge        Merge Junit XML format reports with junitparser.\n      verify       Return a non-zero exit code if one of the testcases failed or errored.\n\n    optional arguments:\n    -h, --help     show this help message and exit\n    -v, --version  show program's version number and exit\n\n\n.. code-block:: console\n\n    $ junitparser merge --help\n    usage: junitparser merge [-h] [--glob] paths [paths ...] output\n\n    positional arguments:\n      paths       Original XML path(s).\n      output      Merged XML Path, setting to \"-\" will output console\n\n    optional arguments:\n      -h, --help  show this help message and exit\n      --glob      Treat original XML path(s) as glob(s).\n      --suite-name SUITE_NAME\n                  Name added to \u003ctestsuites\u003e.\n\n.. code-block:: console\n\n    $ junitparser verify --help\n    usage: junitparser verify [-h] [--glob] paths [paths ...]\n\n    positional arguments:\n      paths       XML path(s) of reports to verify.\n\n    optional arguments:\n      -h, --help  show this help message and exit\n      --glob      Treat original XML path(s) as glob(s).\n\nTest\n----\n\nThe tests are written with python ``unittest``, to run them, use\n`pytest \u003chttps://pypi.org/project/pytest/\u003e`_::\n\n    pytest\n\nIf you get a failure like ``unsupported locale setting`` you may need to add\nextra locales that the tests use. Refer to the steps used in the\n`CI build workflow \u003c.github/workflows/build.yml\u003e`_::\n\n        sudo locale-gen en_US.UTF-8\n        sudo locale-gen de_DE.UTF-8\n        sudo update-locale\n\nContribute\n----------\n\nPRs are welcome!\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fweiwei%2Fjunitparser","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fweiwei%2Fjunitparser","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fweiwei%2Fjunitparser/lists"}