mirror of
https://github.com/httpie/cli.git
synced 2024-11-24 08:22:22 +02:00
Don't inconsistently add XML declarations (#1227)
This commit is contained in:
parent
4f7f59b990
commit
3db1cdba4c
@ -15,6 +15,7 @@ This project adheres to [Semantic Versioning](https://semver.org/).
|
||||
- Added support for basic JSON types on `--form`/`--multipart` when using JSON only operators (`:=`/`:=@`). ([#1212](https://github.com/httpie/httpie/issues/1212))
|
||||
- Added support for automatically enabling `--stream` when `Content-Type` is `text/event-stream`. ([#376](https://github.com/httpie/httpie/issues/376))
|
||||
- Broken plugins will no longer crash the whole application. ([#1204](https://github.com/httpie/httpie/issues/1204))
|
||||
- Fixed auto addition of XML declaration to every formatted XML response. ([#1156](https://github.com/httpie/httpie/issues/1156))
|
||||
|
||||
## [2.6.0](https://github.com/httpie/httpie/compare/2.5.0...2.6.0) (2021-10-14)
|
||||
|
||||
|
@ -1747,7 +1747,9 @@ Formatting has the following effects:
|
||||
to the characters they represent.
|
||||
- XML and XHTML data is indented.
|
||||
|
||||
You can further control the applied formatting via the more granular [format options](#format-options).
|
||||
Please note that sometimes there might be changes made by formatters on the actual response body (e.g
|
||||
collapsing empty tags on XML) but the end result will always be semantically indistinguishable. Some of
|
||||
these formatting changes can be configured more granularly through [format options](#format-options).
|
||||
|
||||
### Format options
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
import sys
|
||||
from typing import TYPE_CHECKING, Optional
|
||||
|
||||
from ...encoding import UTF8
|
||||
@ -8,27 +7,47 @@ if TYPE_CHECKING:
|
||||
from xml.dom.minidom import Document
|
||||
|
||||
|
||||
XML_DECLARATION_OPEN = '<?xml'
|
||||
XML_DECLARATION_CLOSE = '?>'
|
||||
|
||||
|
||||
def parse_xml(data: str) -> 'Document':
|
||||
"""Parse given XML `data` string into an appropriate :class:`~xml.dom.minidom.Document` object."""
|
||||
from defusedxml.minidom import parseString
|
||||
return parseString(data)
|
||||
|
||||
|
||||
def parse_declaration(raw_body: str) -> Optional[str]:
|
||||
body = raw_body.strip()
|
||||
# XMLDecl ::= '<?xml' DECL_CONTENT '?>'
|
||||
if body.startswith(XML_DECLARATION_OPEN):
|
||||
end = body.find(XML_DECLARATION_CLOSE)
|
||||
if end != -1:
|
||||
return body[:end + len(XML_DECLARATION_CLOSE)]
|
||||
|
||||
|
||||
def pretty_xml(document: 'Document',
|
||||
declaration: Optional[str] = None,
|
||||
encoding: Optional[str] = UTF8,
|
||||
indent: int = 2,
|
||||
standalone: Optional[bool] = None) -> str:
|
||||
indent: int = 2) -> str:
|
||||
"""Render the given :class:`~xml.dom.minidom.Document` `document` into a prettified string."""
|
||||
kwargs = {
|
||||
'encoding': encoding or UTF8,
|
||||
'indent': ' ' * indent,
|
||||
}
|
||||
if standalone is not None and sys.version_info >= (3, 9):
|
||||
kwargs['standalone'] = standalone
|
||||
body = document.toprettyxml(**kwargs).decode(kwargs['encoding'])
|
||||
|
||||
# Remove blank lines automatically added by `toprettyxml()`.
|
||||
return '\n'.join(line for line in body.splitlines() if line.strip())
|
||||
lines = [line for line in body.splitlines() if line.strip()]
|
||||
|
||||
# xml.dom automatically adds the declaration, even if
|
||||
# it is not present in the actual body. Remove it.
|
||||
if len(lines) >= 1 and parse_declaration(lines[0]):
|
||||
lines.pop(0)
|
||||
if declaration:
|
||||
lines.insert(0, declaration)
|
||||
|
||||
return '\n'.join(lines)
|
||||
|
||||
|
||||
class XMLFormatter(FormatterPlugin):
|
||||
@ -44,6 +63,7 @@ class XMLFormatter(FormatterPlugin):
|
||||
from xml.parsers.expat import ExpatError
|
||||
from defusedxml.common import DefusedXmlException
|
||||
|
||||
declaration = parse_declaration(body)
|
||||
try:
|
||||
parsed_body = parse_xml(body)
|
||||
except ExpatError:
|
||||
@ -54,6 +74,6 @@ class XMLFormatter(FormatterPlugin):
|
||||
body = pretty_xml(parsed_body,
|
||||
encoding=parsed_body.encoding,
|
||||
indent=self.format_options['xml']['indent'],
|
||||
standalone=parsed_body.standalone)
|
||||
declaration=declaration)
|
||||
|
||||
return body
|
||||
|
3
tests/fixtures/xmldata/valid/custom-header.xml
vendored
Normal file
3
tests/fixtures/xmldata/valid/custom-header.xml
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!-- comment -->
|
||||
<root><element key="value">text</element><element>text</element>tail<empty-element/></root>
|
||||
<!-- comment -->
|
9
tests/fixtures/xmldata/valid/custom-header_formatted.xml
vendored
Normal file
9
tests/fixtures/xmldata/valid/custom-header_formatted.xml
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- comment -->
|
||||
<root>
|
||||
<element key="value">text</element>
|
||||
<element>text</element>
|
||||
tail
|
||||
<empty-element/>
|
||||
</root>
|
||||
|
@ -1,4 +1,3 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?pi data?>
|
||||
<!-- comment -->
|
||||
<root xmlns="namespace">
|
||||
|
1
tests/fixtures/xmldata/valid/simple-single-tag_formatted.xml
vendored
Normal file
1
tests/fixtures/xmldata/valid/simple-single-tag_formatted.xml
vendored
Normal file
@ -0,0 +1 @@
|
||||
<a/>
|
1
tests/fixtures/xmldata/valid/simple-single-tag_raw.xml
vendored
Normal file
1
tests/fixtures/xmldata/valid/simple-single-tag_raw.xml
vendored
Normal file
@ -0,0 +1 @@
|
||||
<a></a>
|
@ -1,4 +1,3 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- comment -->
|
||||
<root>
|
||||
<element key="value">text</element>
|
||||
|
Loading…
Reference in New Issue
Block a user