Π Π΅Π°Π»ΠΈΠ·Π°ΡΠΈΡ ΡΡΠ°Π½ΡΡΠΎΡΠΌΠ°ΡΠΈΠΈ Exclusive XML Canonicalization ΡΠΎΠ³Π»Π°ΡΠ½ΠΎ ΡΠΏΠ΅ΡΠΈΡΠΈΠΊΠ°ΡΠΈΠΈ W3C Π΄Π»Ρ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΡ Π² XML ΠΏΠΎΠ΄ΠΏΠΈΡΡΡ ΠΏΠΎ ΡΡΠ°Π½Π΄Π°ΡΡΡ ΠΠΠ‘Π’.
Π§Π°ΡΡΡ ΠΏΡΠΎΠ΅ΠΊΡΠ° giis-signer - Π±ΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊΠ° Π΄Π»Ρ ΠΏΠΎΠ΄ΠΏΠΈΡΠΈ XML Π΄ΠΎΠΊΡΠΌΠ΅Π½ΡΠΎΠ² ΠΏΠΎ ΠΠΠ‘Π’ Π² ΡΠΈΡΡΠ΅ΠΌΠ΅ ΠΠΠΠ‘ ΠΠΠΠ
ΠΡΠΎΡ ΠΌΠΎΠ΄ΡΠ»Ρ ΡΠ΅Π°Π»ΠΈΠ·ΡΠ΅Ρ Π°Π»Π³ΠΎΡΠΈΡΠΌ Exclusive XML Canonicalization (ExcC14N), ΠΊΠΎΡΠΎΡΡΠΉ ΡΠ²Π»ΡΠ΅ΡΡΡ ΠΊΡΠΈΡΠΈΡΠ΅ΡΠΊΠΈ Π²Π°ΠΆΠ½ΡΠΌ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½ΡΠΎΠΌ Π΄Π»Ρ ΡΠΎΠ·Π΄Π°Π½ΠΈΡ XML ΡΠΈΡΡΠΎΠ²ΡΡ ΠΏΠΎΠ΄ΠΏΠΈΡΠ΅ΠΉ. ΠΠΎΠ΄ΡΠ»Ρ ΡΠΎΠ·Π΄Π°Π½ Π½Π° ΠΎΡΠ½ΠΎΠ²Π΅ Π°Π½Π°Π»ΠΈΠ·Π° Π±ΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊΠΈ GostCryptography Π΄Π»Ρ ΠΎΠ±Π΅ΡΠΏΠ΅ΡΠ΅Π½ΠΈΡ ΡΠΎΠ²ΠΌΠ΅ΡΡΠΈΠΌΠΎΡΡΠΈ Ρ ΡΠΎΡΡΠΈΠΉΡΠΊΠΈΠΌΠΈ ΡΡΠ°Π½Π΄Π°ΡΡΠ°ΠΌΠΈ ΡΠΈΡΡΠΎΠ²ΠΎΠΉ ΠΏΠΎΠ΄ΠΏΠΈΡΠΈ.
xmlcanon/
βββ xmlcanon/ # ΠΡΠ½ΠΎΠ²Π½ΠΎΠΉ ΠΏΠ°ΠΊΠ΅Ρ
β βββ __init__.py # ΠΡΠ±Π»ΠΈΡΠ½ΡΠΉ API
β βββ transform.py # ΠΡΠ½ΠΎΠ²Π½Π°Ρ Π»ΠΎΠ³ΠΈΠΊΠ° ExcC14N
β βββ exceptions.py # ΠΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΠ΅Π»ΡΡΠΊΠΈΠ΅ ΠΈΡΠΊΠ»ΡΡΠ΅Π½ΠΈΡ
βββ tests/ # Π’Π΅ΡΡΡ
β βββ __init__.py
β βββ test_transform.py # 14 unit ΡΠ΅ΡΡΠΎΠ²
βββ examples/ # ΠΡΠΈΠΌΠ΅ΡΡ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΡ
β βββ __init__.py
β βββ basic_usage.py # ΠΠ°Π·ΠΎΠ²ΡΠ΅ ΠΏΡΠΈΠΌΠ΅ΡΡ
β βββ gost_integration.py # ΠΠ½ΡΠ΅Π³ΡΠ°ΡΠΈΡ Ρ ΠΠΠ‘Π’
β βββ performance_test.py # Π’Π΅ΡΡΡ ΠΏΡΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡΠ΅Π»ΡΠ½ΠΎΡΡΠΈ
βββ docs/ # ΠΠΎΠΊΡΠΌΠ΅Π½ΡΠ°ΡΠΈΡ
β βββ CHANGELOG.md # ΠΡΡΠΎΡΠΈΡ ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠΉ
β βββ CONTRIBUTING.md # Π ΡΠΊΠΎΠ²ΠΎΠ΄ΡΡΠ²ΠΎ ΡΠ°Π·ΡΠ°Π±ΠΎΡΡΠΈΠΊΠ°
βββ setup.py # Π£ΡΡΠ°Π½ΠΎΠ²ΠΎΡΠ½ΡΠΉ ΡΠΊΡΠΈΠΏΡ
βββ requirements.txt # ΠΠ°Π²ΠΈΡΠΈΠΌΠΎΡΡΠΈ
βββ MANIFEST.in # Π€Π°ΠΉΠ»Ρ Π΄Π»Ρ Π²ΠΊΠ»ΡΡΠ΅Π½ΠΈΡ Π² ΠΏΠ°ΠΊΠ΅Ρ
βββ LICENSE # MIT Π»ΠΈΡΠ΅Π½Π·ΠΈΡ
βββ README.md # ΠΡΠ½ΠΎΠ²Π½Π°Ρ Π΄ΠΎΠΊΡΠΌΠ΅Π½ΡΠ°ΡΠΈΡ
- β ΠΠΎΠ»Π½Π°Ρ ΡΠΎΠ²ΠΌΠ΅ΡΡΠΈΠΌΠΎΡΡΡ Ρ W3C ΡΠΏΠ΅ΡΠΈΡΠΈΠΊΠ°ΡΠΈΠ΅ΠΉ Exclusive XML Canonicalization
- β ΠΡΠΊΠ»ΡΡΠ΅Π½ΠΈΠ΅ Π½Π΅ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠ΅ΠΌΡΡ ΠΏΡΠΎΡΡΡΠ°Π½ΡΡΠ² ΠΈΠΌΠ΅Π½ - ΠΊΠ»ΡΡΠ΅Π²Π°Ρ ΠΎΡΠΎΠ±Π΅Π½Π½ΠΎΡΡΡ ExcC14N
- β ΠΡΠΈΠ½ΡΠ΄ΠΈΡΠ΅Π»ΡΠ½ΠΎΠ΅ Π²ΠΊΠ»ΡΡΠ΅Π½ΠΈΠ΅ ΠΎΠΏΡΠ΅Π΄Π΅Π»Π΅Π½Π½ΡΡ ΠΏΡΠΎΡΡΡΠ°Π½ΡΡΠ² ΠΈΠΌΠ΅Π½
- β ΠΠΎΡΡΠ΅ΠΊΡΠ½Π°Ρ ΡΠΎΡΡΠΈΡΠΎΠ²ΠΊΠ° Π°ΡΡΠΈΠ±ΡΡΠΎΠ² ΡΠΎΠ³Π»Π°ΡΠ½ΠΎ ΠΊΠ°Π½ΠΎΠ½ΠΈΠ·Π°ΡΠΈΠΈ
- β ΠΡΠ°Π²ΠΈΠ»ΡΠ½ΠΎΠ΅ ΡΠΊΡΠ°Π½ΠΈΡΠΎΠ²Π°Π½ΠΈΠ΅ ΡΠ΅ΠΊΡΡΠ° ΠΈ Π·Π½Π°ΡΠ΅Π½ΠΈΠΉ Π°ΡΡΠΈΠ±ΡΡΠΎΠ²
- β ΠΠΎΠ΄Π΄Π΅ΡΠΆΠΊΠ° Π²Π»ΠΎΠΆΠ΅Π½Π½ΡΡ ΡΡΡΡΠΊΡΡΡ Π»ΡΠ±ΠΎΠΉ ΡΠ»ΠΎΠΆΠ½ΠΎΡΡΠΈ
- β ΠΠ±ΡΠ°Π±ΠΎΡΠΊΠ° ΠΎΡΠΈΠ±ΠΎΠΊ ΠΈ Π²Π°Π»ΠΈΠ΄Π°ΡΠΈΡ Π²Ρ ΠΎΠ΄Π½ΡΡ Π΄Π°Π½Π½ΡΡ
- β Π‘ΠΎΠ²ΠΌΠ΅ΡΡΠΈΠΌΠΎΡΡΡ Ρ lxml ΠΈ ΡΡΠ°Π½Π΄Π°ΡΡΠ½ΠΎΠΉ Π±ΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊΠΎΠΉ
- β 14 unit ΡΠ΅ΡΡΠΎΠ² ΠΏΠΎΠΊΡΡΠ²Π°ΡΡ Π²ΡΠ΅ ΡΡΠ΅Π½Π°ΡΠΈΠΈ
pip install xmlcanon# Π‘ ΠΏΠΎΠ΄Π΄Π΅ΡΠΆΠΊΠΎΠΉ lxml (ΡΠ΅ΠΊΠΎΠΌΠ΅Π½Π΄ΡΠ΅ΡΡΡ Π΄Π»Ρ Π»ΡΡΡΠ΅ΠΉ ΠΏΡΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡΠ΅Π»ΡΠ½ΠΎΡΡΠΈ)
pip install xmlcanon[lxml]
# ΠΠ»Ρ ΡΠ°Π·ΡΠ°Π±ΠΎΡΠΊΠΈ
pip install xmlcanon[dev]git clone https://github.com/imdeniil/xmlcanon.git
cd xmlcanon
pip install -e .- Python 3.6+
- lxml >= 4.0.0 (ΠΎΠΏΡΠΈΠΎΠ½Π°Π»ΡΠ½ΠΎ, ΡΠ΅ΠΊΠΎΠΌΠ΅Π½Π΄ΡΠ΅ΡΡΡ Π΄Π»Ρ Π»ΡΡΡΠ΅ΠΉ ΠΏΡΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡΠ΅Π»ΡΠ½ΠΎΡΡΠΈ)
from xmlcanon import canonicalize_xml
xml_input = '''<root xmlns:ns="http://example.com/ns">
<ns:element attr="value">Π‘ΠΎΠ΄Π΅ΡΠΆΠΈΠΌΠΎΠ΅</ns:element>
</root>'''
canonicalized = canonicalize_xml(xml_input)
print(canonicalized)from xmlcanon import XmlCanonicalizer
# Π‘ΠΎΠ·Π΄Π°Π½ΠΈΠ΅ ΠΊΠ°Π½ΠΎΠ½ΠΈΠ·Π°ΡΠΎΡΠ° Ρ ΠΏΡΠΈΠ½ΡΠ΄ΠΈΡΠ΅Π»ΡΠ½ΡΠΌ Π²ΠΊΠ»ΡΡΠ΅Π½ΠΈΠ΅ΠΌ ΠΏΡΠΎΡΡΡΠ°Π½ΡΡΠ² ΠΈΠΌΠ΅Π½
canonicalizer = XmlCanonicalizer(
inclusive_ns_prefixes=['force', 'include']
)
canonicalized = canonicalizer.transform(xml_input)Π£Π΄ΠΎΠ±Π½Π°Ρ ΡΡΠ½ΠΊΡΠΈΡ Π΄Π»Ρ Π±ΡΡΡΡΠΎΠ³ΠΎ ΠΏΡΠΈΠΌΠ΅Π½Π΅Π½ΠΈΡ XML ΠΊΠ°Π½ΠΎΠ½ΠΈΠ·Π°ΡΠΈΠΈ.
ΠΠ°ΡΠ°ΠΌΠ΅ΡΡΡ:
xml_input(str): ΠΡΡ ΠΎΠ΄Π½ΡΠΉ XML Π΄ΠΎΠΊΡΠΌΠ΅Π½Ρinclusive_ns_prefixes(List[str], optional): ΠΡΠ΅ΡΠΈΠΊΡΡ ΠΏΡΠΎΡΡΡΠ°Π½ΡΡΠ² ΠΈΠΌΠ΅Π½ Π΄Π»Ρ ΠΏΡΠΈΠ½ΡΠ΄ΠΈΡΠ΅Π»ΡΠ½ΠΎΠ³ΠΎ Π²ΠΊΠ»ΡΡΠ΅Π½ΠΈΡ
ΠΠΎΠ·Π²ΡΠ°ΡΠ°Π΅Ρ:
str: ΠΠ°Π½ΠΎΠ½ΠΈΠ·ΠΈΡΠΎΠ²Π°Π½Π½ΡΠΉ XML
ΠΡΠΊΠ»ΡΡΠ΅Π½ΠΈΡ:
InvalidXMLError: ΠΡΠΈ Π½Π΅ΠΊΠΎΡΡΠ΅ΠΊΡΠ½ΠΎΠΌ Π²Ρ ΠΎΠ΄Π½ΠΎΠΌ XMLTransformationError: ΠΡΠΈ ΠΎΡΠΈΠ±ΠΊΠ΅ ΡΡΠ°Π½ΡΡΠΎΡΠΌΠ°ΡΠΈΠΈ
ΠΡΠ½ΠΎΠ²Π½ΠΎΠΉ ΠΊΠ»Π°ΡΡ Π΄Π»Ρ Π²ΡΠΏΠΎΠ»Π½Π΅Π½ΠΈΡ XML ΠΊΠ°Π½ΠΎΠ½ΠΈΠ·Π°ΡΠΈΠΈ.
ΠΠ°ΡΠ°ΠΌΠ΅ΡΡΡ:
inclusive_ns_prefixes(List[str], optional): Π‘ΠΏΠΈΡΠΎΠΊ ΠΏΡΠ΅ΡΠΈΠΊΡΠΎΠ² ΠΏΡΠΎΡΡΡΠ°Π½ΡΡΠ² ΠΈΠΌΠ΅Π½ Π΄Π»Ρ ΠΏΡΠΈΠ½ΡΠ΄ΠΈΡΠ΅Π»ΡΠ½ΠΎΠ³ΠΎ Π²ΠΊΠ»ΡΡΠ΅Π½ΠΈΡ
ΠΡΠΈΠΌΠ΅Π½ΡΠ΅Ρ ΠΊΠ°Π½ΠΎΠ½ΠΈΠ·Π°ΡΠΈΡ ΠΊ XML Π΄ΠΎΠΊΡΠΌΠ΅Π½ΡΡ.
ΠΠΎΠ·Π²ΡΠ°ΡΠ°Π΅Ρ:
str: ΠΠ°Π½ΠΎΠ½ΠΈΠ·ΠΈΡΠΎΠ²Π°Π½Π½ΡΠΉ XML
from xmlcanon.exceptions import InvalidXMLError, TransformationError
try:
result = canonicalize_xml(xml_input)
except InvalidXMLError as e:
print(f"ΠΠ΅ΠΊΠΎΡΡΠ΅ΠΊΡΠ½ΡΠΉ XML: {e}")
except TransformationError as e:
print(f"ΠΡΠΈΠ±ΠΊΠ° ΡΡΠ°Π½ΡΡΠΎΡΠΌΠ°ΡΠΈΠΈ: {e}")from xmlcanon import canonicalize_xml
xml_input = '''<root xmlns:used="http://used.com"
xmlns:unused="http://unused.com">
<used:element>Π’ΠΎΠ»ΡΠΊΠΎ used ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠ΅ΡΡΡ</used:element>
</root>'''
result = canonicalize_xml(xml_input)
# Π Π΅Π·ΡΠ»ΡΡΠ°Ρ ΠΠ Π±ΡΠ΄Π΅Ρ ΡΠΎΠ΄Π΅ΡΠΆΠ°ΡΡ xmlns:unusedsoap_xml = '''<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:ns="urn://xsd.dmdk.goznak.ru/exchange/1.0">
<soapenv:Header/>
<soapenv:Body>
<ns:SendDealRequest>
<ns:RequestData id="body">
<content>ΠΠ°Π½Π½ΡΠ΅ Π΄Π»Ρ ΠΏΠΎΠ΄ΠΏΠΈΡΠΈ</content>
</ns:RequestData>
</ns:SendDealRequest>
</soapenv:Body>
</soapenv:Envelope>'''
canonicalized = canonicalize_xml(soap_xml)
# ΠΠΎΡΠΎΠ²ΠΎ Π΄Π»Ρ ΠΏΡΠΈΠΌΠ΅Π½Π΅Π½ΠΈΡ ΡΠ»Π΅Π΄ΡΡΡΠΈΡ
ΡΡΠ°Π½ΡΡΠΎΡΠΌΠ°ΡΠΈΠΉ (Π½Π°ΠΏΡΠΈΠΌΠ΅Ρ, Π‘ΠΠΠ)from xmlcanon import XmlCanonicalizer
xml_input = '''<root xmlns:force="http://force.com"
xmlns:used="http://used.com">
<used:element>Π’ΠΎΠ»ΡΠΊΠΎ used ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠ΅ΡΡΡ Π² ΡΠΎΠ΄Π΅ΡΠΆΠΈΠΌΠΎΠΌ</used:element>
</root>'''
canonicalizer = XmlCanonicalizer(inclusive_ns_prefixes=['force'])
result = canonicalizer.transform(xml_input)
# Π Π΅Π·ΡΠ»ΡΡΠ°Ρ ΠΠ£ΠΠΠ’ ΡΠΎΠ΄Π΅ΡΠΆΠ°ΡΡ xmlns:force Π½Π΅ΡΠΌΠΎΡΡΡ Π½Π° Π½Π΅ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΠ΅# ΠΠ°ΠΏΡΡΠΊ Π²ΡΠ΅Ρ
ΡΠ΅ΡΡΠΎΠ²
python -m pytest tests/
# ΠΠ°ΠΏΡΡΠΊ Ρ ΠΏΠΎΠΊΡΡΡΠΈΠ΅ΠΌ
python -m pytest tests/ --cov=xmlcanon --cov-report=html
# ΠΠ°ΠΏΡΡΠΊ ΠΊΠΎΠ½ΠΊΡΠ΅ΡΠ½ΠΎΠ³ΠΎ ΡΠ΅ΡΡΠ°
python -m pytest tests/test_transform.py::TestXmlCanonicalizer::test_simple_element- β ΠΠ°Π·ΠΎΠ²ΡΠ΅ ΠΎΠΏΠ΅ΡΠ°ΡΠΈΠΈ Ρ ΡΠ»Π΅ΠΌΠ΅Π½ΡΠ°ΠΌΠΈ ΠΈ Π°ΡΡΠΈΠ±ΡΡΠ°ΠΌΠΈ
- β ΠΠ±ΡΠ°Π±ΠΎΡΠΊΠ° ΠΏΡΠΎΡΡΡΠ°Π½ΡΡΠ² ΠΈΠΌΠ΅Π½ (ΠΎΠ±ΡΡΠ²Π»Π΅Π½ΠΈΡ, ΠΈΡΠΊΠ»ΡΡΠ΅Π½ΠΈΡ, Π²ΠΊΠ»ΡΡΠ΅Π½ΠΈΡ)
- β Π‘ΠΎΡΡΠΈΡΠΎΠ²ΠΊΠ° Π°ΡΡΠΈΠ±ΡΡΠΎΠ² ΠΈ ΠΏΡΠΎΡΡΡΠ°Π½ΡΡΠ² ΠΈΠΌΠ΅Π½
- β ΠΠΊΡΠ°Π½ΠΈΡΠΎΠ²Π°Π½ΠΈΠ΅ ΡΠ΅ΠΊΡΡΠ° ΠΈ Π·Π½Π°ΡΠ΅Π½ΠΈΠΉ Π°ΡΡΠΈΠ±ΡΡΠΎΠ²
- β Π Π΅Π°Π»ΡΠ½ΡΠ΅ SOAP ΡΡΡΡΠΊΡΡΡΡ (ΠΠΠΠ‘ ΠΠΠΠ)
- β ΠΠ±ΡΠ°Π±ΠΎΡΠΊΠ° ΠΎΡΠΈΠ±ΠΎΠΊ
ΠΡΠΎΡ ΠΌΠΎΠ΄ΡΠ»Ρ ΠΏΡΠ΅Π΄Π½Π°Π·Π½Π°ΡΠ΅Π½ Π΄Π»Ρ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΡ Π² ΠΊΠ°ΡΠ΅ΡΡΠ²Π΅ ΠΏΠ΅ΡΠ²ΠΎΠΉ ΡΡΠ°Π½ΡΡΠΎΡΠΌΠ°ΡΠΈΠΈ ΠΏΡΠΈ ΡΠΎΠ·Π΄Π°Π½ΠΈΠΈ XML ΠΏΠΎΠ΄ΠΏΠΈΡΠ΅ΠΉ ΠΏΠΎ ΠΠΠ‘Π’:
def create_gost_xml_signature(xml_data, certificate):
# 1. ΠΡΠΈΠΌΠ΅Π½ΡΠ΅ΠΌ XML ΠΊΠ°Π½ΠΎΠ½ΠΈΠ·Π°ΡΠΈΡ
canonicalized = canonicalize_xml(xml_data)
# 2. ΠΡΠΈΠΌΠ΅Π½ΡΠ΅ΠΌ Π‘ΠΠΠ ΡΡΠ°Π½ΡΡΠΎΡΠΌΠ°ΡΠΈΡ (ΠΎΡΠ΄Π΅Π»ΡΠ½ΡΠΉ ΠΌΠΎΠ΄ΡΠ»Ρ)
smev_transformed = apply_smev_transform(canonicalized)
# 3. ΠΡΡΠΈΡΠ»ΡΠ΅ΠΌ Ρ
Π΅Ρ ΠΠΠ‘Π’
digest = compute_gost_digest(smev_transformed)
# 4. Π‘ΠΎΠ·Π΄Π°Π΅ΠΌ ΠΏΠΎΠ΄ΠΏΠΈΡΡ
signature = create_gost_signature(digest, certificate)
return signature- β W3C Exclusive XML Canonicalization Version 1.0 - ΠΏΠΎΠ»Π½ΠΎΠ΅ ΡΠΎΠΎΡΠ²Π΅ΡΡΡΠ²ΠΈΠ΅
- β XML-DSig ΡΠΏΠ΅ΡΠΈΡΠΈΠΊΠ°ΡΠΈΡ - ΠΏΠΎΠ΄Π΄Π΅ΡΠΆΠΊΠ° ΡΡΠ°Π½ΡΡΠΎΡΠΌΠ°ΡΠΈΠΉ Π΄Π»Ρ ΠΏΠΎΠ΄ΠΏΠΈΡΠ΅ΠΉ
- β ΠΠΠ‘Π’ ΡΡΠ°Π½Π΄Π°ΡΡΡ - ΡΠΎΠ²ΠΌΠ΅ΡΡΠΈΠΌΠΎΡΡΡ Ρ ΡΠΎΡΡΠΈΠΉΡΠΊΠΈΠΌΠΈ ΠΊΡΠΈΠΏΡΠΎΠ³ΡΠ°ΡΠΈΡΠ΅ΡΠΊΠΈΠΌΠΈ ΡΡΠ°Π½Π΄Π°ΡΡΠ°ΠΌΠΈ
- ΠΠ±ΡΠ°Π±ΠΎΡΠΊΠ° XML Π΄ΠΎΠΊΡΠΌΠ΅Π½ΡΠΎΠ² Π΄ΠΎ 1MB
- ΠΠΏΡΠΈΠΌΠΈΠ·Π°ΡΠΈΡ Π΄Π»Ρ ΡΠΈΠΏΠΈΡΠ½ΡΡ SOAP ΡΡΡΡΠΊΡΡΡ
- ΠΠΈΠ½ΠΈΠΌΠ°Π»ΡΠ½ΠΎΠ΅ ΠΏΠΎΡΡΠ΅Π±Π»Π΅Π½ΠΈΠ΅ ΠΏΠ°ΠΌΡΡΠΈ
- ΠΠΎΠ΄Π΄Π΅ΡΠΆΠΊΠ° Π±ΠΎΠ»ΡΡΠΈΡ Π΄ΠΎΠΊΡΠΌΠ΅Π½ΡΠΎΠ² ΡΠ΅ΡΠ΅Π· ΠΏΠΎΡΠΎΠΊΠΎΠ²ΡΡ ΠΎΠ±ΡΠ°Π±ΠΎΡΠΊΡ (ΠΏΠ»Π°Π½ΠΈΡΡΠ΅ΡΡΡ)
- ΠΠ°Π»ΡΠΉ XML (< 1KB): ~0.001 ΡΠ΅ΠΊ
- Π‘ΡΠ΅Π΄Π½ΠΈΠΉ XML (10-50KB): ~0.005 ΡΠ΅ΠΊ
- ΠΠΎΠ»ΡΡΠΎΠΉ XML (100KB+): ~0.020 ΡΠ΅ΠΊ
# ΠΠ»ΠΎΠ½ΠΈΡΠΎΠ²Π°Π½ΠΈΠ΅ ΡΠ΅ΠΏΠΎΠ·ΠΈΡΠΎΡΠΈΡ
git clone https://github.com/imdeniil/xmlcanon.git
cd xmlcanon
# Π‘ΠΎΠ·Π΄Π°Π½ΠΈΠ΅ Π²ΠΈΡΡΡΠ°Π»ΡΠ½ΠΎΠ³ΠΎ ΠΎΠΊΡΡΠΆΠ΅Π½ΠΈΡ
python -m venv venv
source venv/bin/activate # Linux/Mac
# ΠΈΠ»ΠΈ
venv\Scripts\activate # Windows
# Π£ΡΡΠ°Π½ΠΎΠ²ΠΊΠ° Π² ΡΠ΅ΠΆΠΈΠΌΠ΅ ΡΠ°Π·ΡΠ°Π±ΠΎΡΠΊΠΈ
pip install -e ".[dev]"# Π€ΠΎΡΠΌΠ°ΡΠΈΡΠΎΠ²Π°Π½ΠΈΠ΅ ΠΊΠΎΠ΄Π°
black xmlcanon/ tests/ examples/
# ΠΡΠΎΠ²Π΅ΡΠΊΠ° ΡΡΠΈΠ»Ρ
flake8 xmlcanon/ tests/ examples/
# ΠΡΠΎΠ²Π΅ΡΠΊΠ° ΡΠΈΠΏΠΎΠ²
mypy xmlcanon/- README: ΠΡΠ½ΠΎΠ²Π½Π°Ρ Π΄ΠΎΠΊΡΠΌΠ΅Π½ΡΠ°ΡΠΈΡ (ΡΡΠΎΡ ΡΠ°ΠΉΠ»)
- LLM Guide: Quick Start Π΄Π»Ρ LLM - ΠΊΡΠ°ΡΠΊΠΎΠ΅ ΡΡΠΊΠΎΠ²ΠΎΠ΄ΡΡΠ²ΠΎ Π΄Π»Ρ Π±ΡΡΡΡΠΎΠ³ΠΎ ΡΡΠ°ΡΡΠ°
- CONTRIBUTING: Π ΡΠΊΠΎΠ²ΠΎΠ΄ΡΡΠ²ΠΎ Π΄Π»Ρ ΡΠ°Π·ΡΠ°Π±ΠΎΡΡΠΈΠΊΠΎΠ²
- CHANGELOG: ΠΡΡΠΎΡΠΈΡ ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠΉ
ΠΠΎΠ΄ΡΠ»Ρ ΠΎΡΠΊΡΡΡ Π΄Π»Ρ Π΄ΠΎΡΠ°Π±ΠΎΡΠΎΠΊ ΠΈ ΡΠ»ΡΡΡΠ΅Π½ΠΈΠΉ:
- Issues: GitHub Issues
- Pull Requests: ΠΏΡΠΈΠ²Π΅ΡΡΡΠ²ΡΡΡΡΡ ΡΠ»ΡΡΡΠ΅Π½ΠΈΡ
- ΠΠΎΠΊΡΠΌΠ΅Π½ΡΠ°ΡΠΈΡ: Π² docs/CONTRIBUTING.md
- Π‘ΡΠΈΠ»Ρ ΠΊΠΎΠ΄Π°: Black + PEP 8
ΠΡΠΎΡ ΠΏΡΠΎΠ΅ΠΊΡ ΡΠ°ΡΠΏΡΠΎΡΡΡΠ°Π½ΡΠ΅ΡΡΡ ΠΏΠΎΠ΄ Π»ΠΈΡΠ΅Π½Π·ΠΈΠ΅ΠΉ MIT. Π‘ΠΌ. ΡΠ°ΠΉΠ» LICENSE Π΄Π»Ρ ΠΏΠΎΠ΄ΡΠΎΠ±Π½ΠΎΡΡΠ΅ΠΉ.
- PyPI: https://pypi.org/project/xmlcanon/
- GitHub: https://github.com/imdeniil/xmlcanon
- Issues: https://github.com/imdeniil/xmlcanon/issues
- Email: [email protected]
- ΠΠ²ΡΠΎΡ: Daniil (imdeniil)
- ΠΠ΅ΡΠ²ΡΠΉ ΡΠ΅Π»ΠΈΠ·
- ΠΠΎΠ»Π½Π°Ρ ΡΠ΅Π°Π»ΠΈΠ·Π°ΡΠΈΡ ExcC14N ΡΠΎΠ³Π»Π°ΡΠ½ΠΎ W3C ΡΠΏΠ΅ΡΠΈΡΠΈΠΊΠ°ΡΠΈΠΈ
- ΠΠΎΠ΄Π΄Π΅ΡΠΆΠΊΠ° lxml ΠΈ ΡΡΠ°Π½Π΄Π°ΡΡΠ½ΠΎΠΉ Π±ΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊΠΈ
- ΠΠΎΠ»Π½ΠΎΠ΅ ΠΏΠΎΠΊΡΡΡΠΈΠ΅ ΡΠ΅ΡΡΠ°ΠΌΠΈ (14 ΡΠ΅ΡΡΠΎΠ²)
- Π‘ΠΎΠ²ΠΌΠ΅ΡΡΠΈΠΌΠΎΡΡΡ Ρ ΠΠΠ‘Π’ ΡΡΠ°Π½Π΄Π°ΡΡΠ°ΠΌΠΈ
Π‘ΠΎΠ·Π΄Π°Π½ΠΎ Π½Π° ΠΎΡΠ½ΠΎΠ²Π΅ Π°Π½Π°Π»ΠΈΠ·Π° Π±ΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊΠΈ GostCryptography