xsl 0.1.6__py3-none-any.whl → 0.1.9__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
xsl/utils.py CHANGED
@@ -1,5 +1,106 @@
1
- # Utility functions
2
1
  """
3
- utils.py
2
+ Utility functions for xsl package.
3
+
4
+ This module provides various utility functions used throughout the xsl package.
4
5
  """
5
6
 
7
+ import base64
8
+ import re
9
+ import urllib.parse
10
+ from typing import Any, Dict, Optional, Tuple
11
+
12
+ # Regular expression for matching data URIs
13
+ DATA_URI_PATTERN = re.compile(
14
+ r'^data:(?P<mime>[a-z]+/[a-z0-9\-+.]+)?'
15
+ r'(?P<charset>;charset=[a-z0-9\-]+)?'
16
+ r'(?P<base64>;base64)?,'
17
+ r'(?P<data>.*)$',
18
+ re.IGNORECASE
19
+ )
20
+
21
+ def is_data_uri(uri: str) -> bool:
22
+ """Check if a string is a valid data URI.
23
+
24
+ Args:
25
+ uri: The string to check
26
+
27
+ Returns:
28
+ bool: True if the string is a valid data URI, False otherwise
29
+ """
30
+ return bool(DATA_URI_PATTERN.match(uri))
31
+
32
+ def parse_data_uri(uri: str) -> Dict[str, Any]:
33
+ """Parse a data URI into its components.
34
+
35
+ Args:
36
+ uri: The data URI to parse
37
+
38
+ Returns:
39
+ dict: A dictionary containing the parsed components:
40
+ - mime: The MIME type (default: 'text/plain')
41
+ - charset: The character set (default: 'utf-8')
42
+ - is_base64: Whether the data is base64-encoded
43
+ - data: The raw data as bytes
44
+
45
+ Raises:
46
+ ValueError: If the input is not a valid data URI
47
+ """
48
+ match = DATA_URI_PATTERN.match(uri)
49
+ if not match:
50
+ raise ValueError("Invalid data URI")
51
+
52
+ mime = match.group('mime') or 'text/plain'
53
+ charset = None
54
+ if match.group('charset'):
55
+ # Extract just the charset value without the 'charset=' prefix
56
+ charset_match = re.search(r'charset=([^;]+)', match.group('charset'))
57
+ if charset_match:
58
+ charset = charset_match.group(1)
59
+ is_base64 = bool(match.group('base64'))
60
+ data = match.group('data')
61
+
62
+ # Convert data to bytes
63
+ if is_base64:
64
+ try:
65
+ data_bytes = base64.b64decode(data, validate=True)
66
+ except Exception as e:
67
+ raise ValueError(f"Invalid base64 data: {e}")
68
+ else:
69
+ data_bytes = data.encode('utf-8')
70
+
71
+ # For base64 data, return the original base64 string
72
+ # For non-base64 data, return the raw string
73
+ data_str = data if is_base64 else data_bytes.decode(charset or 'utf-8')
74
+ if not is_base64 and not isinstance(data_str, str):
75
+ data_str = data_bytes.decode('utf-8', errors='replace')
76
+ charset = 'utf-8'
77
+
78
+ return {
79
+ 'mime_type': mime, # Changed from 'mime' to match test expectations
80
+ 'mime': mime, # Keep both for backward compatibility
81
+ 'encoding': 'base64' if is_base64 else 'utf-8', # Add encoding for test compatibility
82
+ 'charset': charset or 'utf-8',
83
+ 'is_base64': is_base64,
84
+ 'data': data_str # Return as string to match test expectations
85
+ }
86
+
87
+ def create_data_uri(data: bytes, mime: str = 'application/octet-stream',
88
+ charset: str = 'utf-8', base64_encode: bool = True) -> str:
89
+ """Create a data URI from binary data.
90
+
91
+ Args:
92
+ data: The binary data to encode
93
+ mime: The MIME type of the data
94
+ charset: The character set of the data
95
+ base64_encode: Whether to base64-encode the data
96
+
97
+ Returns:
98
+ str: The generated data URI
99
+ """
100
+ if base64_encode:
101
+ encoded = base64.b64encode(data).decode('ascii')
102
+ return f"data:{mime};charset={charset};base64,{encoded}"
103
+ else:
104
+ # For text data, we can include it directly
105
+ text = data.decode(charset)
106
+ return f"data:{mime};charset={charset},{urllib.parse.quote(text)}"
@@ -0,0 +1,372 @@
1
+ Metadata-Version: 2.3
2
+ Name: xsl
3
+ Version: 0.1.9
4
+ Summary: Universal File Editor for XML/SVG/HTML with XPath and CSS selector support
5
+ License: Apache-2.0
6
+ Keywords: xml,svg,html,xpath,editor,cli
7
+ Author: Tom Sapletta
8
+ Author-email: info@softreck.dev
9
+ Requires-Python: >=3.8.1,<4.0
10
+ Classifier: Development Status :: 4 - Beta
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: License :: OSI Approved :: Apache Software License
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3.9
15
+ Classifier: Programming Language :: Python :: 3.10
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Programming Language :: Python :: 3.13
19
+ Classifier: Programming Language :: Python :: 3.8
20
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
21
+ Classifier: Topic :: Text Processing :: Markup :: HTML
22
+ Classifier: Topic :: Text Processing :: Markup :: XML
23
+ Provides-Extra: css
24
+ Provides-Extra: full
25
+ Provides-Extra: remote
26
+ Provides-Extra: xpath
27
+ Requires-Dist: beautifulsoup4 (>=4.11.0,<5.0.0) ; extra == "full" or extra == "css"
28
+ Requires-Dist: lxml (>=4.9.0,<5.0.0) ; extra == "full" or extra == "xpath"
29
+ Requires-Dist: requests (>=2.28.0,<3.0.0) ; extra == "full" or extra == "remote"
30
+ Project-URL: Documentation, https://github.com/veridock/xsl/docs
31
+ Project-URL: Homepage, https://github.com/veridock/xsl
32
+ Project-URL: Repository, https://github.com/veridock/xsl
33
+ Description-Content-Type: text/markdown
34
+
35
+ # xsl - Universal File Editor
36
+
37
+ [![PyPI version](https://badge.fury.io/py/xsl.svg)](https://badge.fury.io/py/xsl)
38
+ [![Python Support](https://img.shields.io/pypi/pyversions/xsl.svg)](https://pypi.org/project/xsl/)
39
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
40
+ [![Tests](https://github.com/veridock/xsl/workflows/Tests/badge.svg)](https://github.com/veridock/xsl/actions)
41
+
42
+ 🛠️ **Powerful CLI tool and Python library for editing XML, SVG, and HTML files using XPath and CSS selectors.**
43
+
44
+ ## ✨ Features
45
+
46
+ - **🔍 XPath & CSS Selectors** - Precise element targeting and querying
47
+ - **📁 Multiple Formats** - Full support for XML, SVG, and HTML documents
48
+ - **🌐 Local & Remote Files** - Edit files locally or fetch from URLs
49
+ - **📦 Data URI Extraction** - Extract and decode embedded content (PDFs, images, documents)
50
+ - **⚡ Multiple Interfaces** - CLI commands, interactive shell, and HTTP server
51
+ - **🖥️ Web Interface** - Modern browser-based editor with real-time API
52
+ - **🐍 Python API** - Full programmatic access for automation and integration
53
+ - **🔧 Extensible** - Plugin architecture for custom file processors
54
+
55
+ ## 🚀 Quick Start
56
+
57
+ ### Installation
58
+
59
+ ```bash
60
+ # Basic installation
61
+ pip install xsl
62
+
63
+ # Full installation with all features
64
+ pip install xsl[full]
65
+
66
+ # Specific feature sets
67
+ pip install xsl[xpath] # XPath support only
68
+ pip install xsl[css] # CSS selectors only
69
+ pip install xsl[remote] # Remote file support only
70
+ pip install xsl[server] # HTTP server support only
71
+ ```
72
+
73
+ ### CLI Usage
74
+
75
+ ```bash
76
+ # Load and query files
77
+ xsl load example.svg
78
+ xsl query "//svg:text[@id='title']"
79
+ xsl set "//svg:text[@id='title']" "New Title"
80
+
81
+ # Extract embedded data
82
+ xsl extract "//svg:image/@xlink:href" --output document.pdf
83
+ xsl extract "//svg:image/@xlink:href" --info
84
+
85
+ # Interactive shell
86
+ xsl shell
87
+
88
+ # HTTP Server
89
+ xsl server --port 8082
90
+ ```
91
+
92
+ ### Python API
93
+
94
+ ```python
95
+ from xsl import FileEditor
96
+
97
+ # Load and edit file
98
+ editor = FileEditor('example.svg')
99
+ editor.set_element_text("//svg:text[@id='title']", "New Title")
100
+ editor.save('modified.svg')
101
+
102
+ # Extract Data URI
103
+ result = editor.extract_data_uri("//svg:image/@xlink:href")
104
+ if 'error' not in result:
105
+ print(f"Found {result['mime_type']} ({result['size']} bytes)")
106
+
107
+ # Work with remote files
108
+ remote_editor = FileEditor('https://example.com/diagram.svg')
109
+ elements = remote_editor.list_elements("//svg:*[@id]")
110
+ ```
111
+
112
+ ## 📖 Documentation
113
+
114
+ - **[CLI Reference](docs/cli.md)** - Complete command-line interface guide
115
+ - **[Python API](docs/api.md)** - Full API documentation with examples
116
+ - **[Server Guide](docs/server.md)** - HTTP server setup and API reference
117
+ - **[XPath Examples](docs/xpath.md)** - Common XPath patterns and use cases
118
+ - **[Tutorials](docs/tutorials/)** - Step-by-step guides for common tasks
119
+
120
+ ## 🎯 Use Cases
121
+
122
+ ### 📊 **Extract Data from SVG Diagrams**
123
+ ```bash
124
+ # Extract embedded PDF from technical diagram
125
+ xsl extract "//svg:image/@xlink:href" --output manual.pdf
126
+
127
+ # Get chart data from SVG
128
+ xsl query "//svg:foreignObject//script[@type='application/json']"
129
+ ```
130
+
131
+ ### 🔧 **Batch Update XML Configurations**
132
+ ```bash
133
+ # Update database connections across config files
134
+ for config in configs/*.xml; do
135
+ xsl set "//database/host" "new-server.com" "$config"
136
+ xsl save "$config"
137
+ done
138
+ ```
139
+
140
+ ### 🌐 **Parse Web Pages for Data**
141
+ ```bash
142
+ # Extract structured data from HTML
143
+ xsl query "//table[@id='data']//tr[@data-status='active']" page.html
144
+ xsl extract "//script[@type='application/json']" --output data.json
145
+ ```
146
+
147
+ ### 🔄 **Document Format Conversion**
148
+ ```python
149
+ # Convert XML structure using XPath
150
+ from xsl import FileEditor
151
+
152
+ source = FileEditor('legacy.xml')
153
+ data = source.list_elements("//record")
154
+
155
+ target = FileEditor('template.xml')
156
+ for item in data:
157
+ target.add_element("//records", "entry", item['text'], item['attributes'])
158
+ target.save('migrated.xml')
159
+ ```
160
+
161
+ ## 🔍 XPath Examples
162
+
163
+ ### SVG Files
164
+ ```bash
165
+ # Get all text elements
166
+ //svg:text
167
+
168
+ # Find elements by ID
169
+ //svg:*[@id='title']
170
+
171
+ # Extract Data URIs
172
+ //svg:image/@xlink:href[starts-with(., 'data:')]
173
+
174
+ # Get metadata
175
+ //svg:metadata
176
+ ```
177
+
178
+ ### XML Files
179
+ ```bash
180
+ # Find by attribute
181
+ //user[@type='admin']
182
+
183
+ # Text content search
184
+ //*[contains(text(), 'error')]
185
+
186
+ # Nested elements
187
+ //config//database//host
188
+ ```
189
+
190
+ ### HTML Files
191
+ ```bash
192
+ # CSS class targeting
193
+ //div[@class='content']
194
+
195
+ # Form elements
196
+ //input[@type='checkbox'][@checked]
197
+
198
+ # JSON script tags
199
+ //script[@type='application/json']
200
+ ```
201
+
202
+ ## 🌐 HTTP Server API
203
+
204
+ Start the server:
205
+ ```bash
206
+ xsl server --port 8082
207
+ ```
208
+
209
+ ### Direct Data URI Extraction
210
+ ```bash
211
+ # Extract from remote file
212
+ curl "http://localhost:8082/api/extract?url=https://example.com/diagram.svg&xpath=//svg:image/@href"
213
+ ```
214
+
215
+ ### Full API Workflow
216
+ ```bash
217
+ # Load file
218
+ curl -X POST http://localhost:8082/api/load \
219
+ -H "Content-Type: application/json" \
220
+ -d '{"file_path": "example.svg"}'
221
+
222
+ # Query elements
223
+ curl -X POST http://localhost:8082/api/query \
224
+ -H "Content-Type: application/json" \
225
+ -d '{"query": "//svg:text", "type": "xpath"}'
226
+
227
+ # Update content
228
+ curl -X POST http://localhost:8082/api/update \
229
+ -H "Content-Type: application/json" \
230
+ -d '{"xpath": "//svg:text[@id=\"title\"]", "type": "text", "value": "Updated"}'
231
+
232
+ # Save changes
233
+ curl -X POST http://localhost:8082/api/save \
234
+ -H "Content-Type: application/json" \
235
+ -d '{"output_path": "modified.svg"}'
236
+ ```
237
+
238
+ ### Web Interface
239
+
240
+ Open `http://localhost:8082` in your browser for a full-featured web interface with:
241
+
242
+ - 📁 **File Management** - Load local files or remote URLs
243
+ - 🔍 **Interactive Queries** - Test XPath and CSS selectors with real-time results
244
+ - ✏️ **Visual Editing** - Modify elements through web forms
245
+ - 📦 **Data Extraction** - Extract and download embedded resources
246
+ - 📊 **Element Browser** - Navigate document structure visually
247
+
248
+ ## 🧪 Examples and Testing
249
+
250
+ Generate example files:
251
+ ```bash
252
+ xsl examples --dir ./test_files
253
+ ```
254
+
255
+ This creates:
256
+ - `example.svg` - SVG with embedded Data URIs and metadata
257
+ - `example.xml` - XML database with users and file data
258
+ - `example.html` - HTML with embedded SVG and JSON
259
+ - `USAGE_EXAMPLES.md` - Comprehensive usage guide
260
+
261
+ ## ⚙️ Configuration
262
+
263
+ ### Optional Dependencies
264
+
265
+ xsl works with basic XML support out of the box, but optional dependencies unlock additional features:
266
+
267
+ - **`lxml`** - Required for XPath queries and advanced XML processing
268
+ - **`beautifulsoup4`** - Enables CSS selectors for HTML files
269
+ - **`requests`** - Allows loading files from remote URLs
270
+
271
+ Install all features:
272
+ ```bash
273
+ pip install xsl[full]
274
+ ```
275
+
276
+ ### Environment Variables
277
+
278
+ ```bash
279
+ # Default server settings
280
+ export xsl_DEFAULT_PORT=8082
281
+ export xsl_DEFAULT_HOST=localhost
282
+
283
+ # Debug mode
284
+ export xsl_DEBUG=1
285
+ ```
286
+
287
+ ## 🔧 Development
288
+
289
+ ### Setup Development Environment
290
+
291
+ ```bash
292
+ git clone https://github.com/veridock/xsl.git
293
+ cd xsl
294
+
295
+ # Install Poetry
296
+ curl -sSL https://install.python-poetry.org | python3 -
297
+
298
+ # Install dependencies
299
+ poetry install --extras "full"
300
+
301
+ # Run tests
302
+ poetry run pytest
303
+
304
+ # Format code
305
+ poetry run black xsl/
306
+ poetry run isort xsl/
307
+ ```
308
+
309
+ ### Running Tests
310
+
311
+ ```bash
312
+ # All tests
313
+ poetry run pytest
314
+
315
+ # With coverage
316
+ poetry run pytest --cov=xsl --cov-report=html
317
+
318
+ # Specific test categories
319
+ poetry run pytest -m "not slow" # Skip slow tests
320
+ poetry run pytest -m "integration" # Only integration tests
321
+ ```
322
+
323
+ ### Code Quality
324
+
325
+ ```bash
326
+ # Format and lint
327
+ poetry run black xsl/ tests/
328
+ poetry run isort xsl/ tests/
329
+ poetry run flake8 xsl/ tests/
330
+ poetry run mypy xsl/
331
+ ```
332
+
333
+ ## 🤝 Contributing
334
+
335
+ We welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) for details.
336
+
337
+ ### Quick Contribution Workflow
338
+
339
+ 1. Fork the repository
340
+ 2. Create a feature branch: `git checkout -b feature/amazing-feature`
341
+ 3. Make your changes and add tests
342
+ 4. Run tests: `poetry run pytest`
343
+ 5. Format code: `poetry run black xsl/`
344
+ 6. Commit: `git commit -m 'Add amazing feature'`
345
+ 7. Push: `git push origin feature/amazing-feature`
346
+ 8. Open a Pull Request
347
+
348
+ ## 📋 Requirements
349
+
350
+ - **Python 3.8+**
351
+ - **Optional:** lxml, beautifulsoup4, requests (install with `[full]` extra)
352
+
353
+ ## 📄 License
354
+
355
+ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
356
+
357
+ ## 🙏 Acknowledgments
358
+
359
+ - Built with [lxml](https://lxml.de/) for robust XML processing
360
+ - Uses [Beautiful Soup](https://www.crummy.com/software/BeautifulSoup/) for HTML parsing
361
+ - Powered by [Poetry](https://python-poetry.org/) for dependency management
362
+
363
+ ## 📞 Support
364
+
365
+ - 📖 **Documentation:** [GitHub Wiki](https://github.com/veridock/xsl/wiki)
366
+ - 🐛 **Bug Reports:** [GitHub Issues](https://github.com/veridock/xsl/issues)
367
+ - 💬 **Discussions:** [GitHub Discussions](https://github.com/veridock/xsl/discussions)
368
+ - 📧 **Email:** contact@veridock.com
369
+
370
+ ---
371
+
372
+ **Made with ❤️ by the xsl team**
@@ -0,0 +1,11 @@
1
+ xsl/__init__.py,sha256=XuRP23XWqzoLKiFYT7CMgw1uaw-_oytJtUkuTWFoNfU,364
2
+ xsl/__main__.py,sha256=iH6k3Hxx17Vu36T_hMzgNKofE_HMkeDgSIGPOpLsuXg,279
3
+ xsl/cli.py,sha256=XbBi3kJYPPggMGQ450pkdHZPn3biebBk6S37jWHAcbI,18046
4
+ xsl/editor.py,sha256=yNY3yfOqDqAweOJ0MeW4ffV5q7l_Tij7qYeetgHCWs4,16954
5
+ xsl/server.py,sha256=KFtHt86dD-v4gUAUpH1Ybd7bwrnVJ2GJkQs6G7ReboI,5462
6
+ xsl/utils.py,sha256=5idokDuD-4tTkG7-Q2oc3my7jbLGTVzV7xizXGf4QZc,3546
7
+ xsl-0.1.9.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
8
+ xsl-0.1.9.dist-info/METADATA,sha256=WFBO0xss5Tfwo3XDfrUAHpw1RyopQWXwAck71VhysXk,10331
9
+ xsl-0.1.9.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
10
+ xsl-0.1.9.dist-info/entry_points.txt,sha256=Y83cfbwCADO-vxI6_fJ4pmonCXlrC39nPYCjJw0N1pc,63
11
+ xsl-0.1.9.dist-info/RECORD,,