QwQ Tag
A lightweight Python library for parsing XML/HTML content into structured, type-safe objects using Pydantic models. qwq-tag provides a simple and intuitive way to work with XML/HTML data while maintaining strong type safety and validation.
Features
- 🚀 Simple API: Parse XML/HTML strings with a single method call
- 🔒 Type Safety: Built on Pydantic for robust data validation and type hints
- 🌐 Flexible Parsing: Handles malformed XML/HTML with recovery parsing
- 📦 Lightweight: Minimal dependencies (only
lxmlandpydantic) - 🎯 Mixed Content Support: Properly handles text and nested elements
- 🔄 Multiple Root Elements: Can parse fragments with multiple top-level elements
- 🧹 Clean Output: Automatically handles whitespace normalization
Installation
Using pip
pip install qwq-tag
Using PDM
pdm add qwq-tag
Requirements
- Python 3.10+
- lxml >= 6.0.0
- pydantic >= 2.11.7
Quick Start
from qwq_tag import QwqTag
# Parse simple XML
html = '<div class="container">Hello World</div>'
tags = QwqTag.from_str(html)
# Access the parsed content
tag = tags[0]
print(tag.name) # "div"
print(tag.content) # ["Hello World"]
print(tag.attr) # {"class": "container"}
print(tag.content_text) # "Hello World"
Usage Examples
Basic XML Parsing
from qwq_tag import QwqTag
# Simple element with attributes
xml = '<p class="text" id="intro">Hello World</p>'
result = QwqTag.from_str(xml)
tag = result[0]
print(f"Tag: {tag.name}") # Tag: p
print(f"Content: {tag.content}") # Content: ['Hello World']
print(f"Class: {tag.attr['class']}") # Class: text
print(f"ID: {tag.attr['id']}") # ID: intro
Nested Elements
# Nested structure
xml = """
<div class="container">
<h1>Title</h1>
<p>Paragraph content</p>
</div>
"""
result = QwqTag.from_str(xml)
div_tag = result[0]
print(f"Container has {len(div_tag.content)} children")
for child in div_tag.content:
if isinstance(child, QwqTag):
print(f"- {child.name}: {child.content_text}")
Mixed Content (Text + Elements)
# Mixed content with text and nested elements
xml = '<p>Before <strong>bold text</strong> and <em>italic</em> after</p>'
result = QwqTag.from_str(xml)
p_tag = result[0]
print("Content breakdown:")
for item in p_tag.content:
if isinstance(item, str):
print(f" Text: '{item}'")
else:
print(f" Element: <{item.name}>{item.content_text}</{item.name}>")
# Output:
# Text: 'Before'
# Element: <strong>bold text</strong>
# Text: 'and'
# Element: <em>italic</em>
# Text: 'after'
Multiple Root Elements
# Fragment with multiple root elements
xml = '<h1>Title</h1><p>First paragraph</p><p>Second paragraph</p>'
result = QwqTag.from_str(xml)
print(f"Found {len(result)} root elements:")
for tag in result:
print(f"- {tag.name}: {tag.content_text}")
# Output:
# Found 3 root elements:
# - h1: Title
# - p: First paragraph
# - p: Second paragraph
Error Recovery
# Malformed XML/HTML
malformed = '<div><p>Unclosed paragraph<span>Text</div>'
try:
result = QwqTag.from_str(malformed)
print("Successfully parsed malformed XML!")
print(str(result[0]))
except Exception as e:
print(f"Parsing failed: {e}")
Converting Back to String
# Create a tag programmatically
tag = QwqTag(
name="article",
content=["Article content"],
attr={"class": "post", "id": "123"}
)
print(str(tag))
# Output: <article class="post" id="123">Article content</article>
Development
Setup Development Environment
# Clone the repository
git clone https://github.com/yanli/qwq-tag.git
cd qwq-tag
# Install PDM if you haven't already
pip install pdm
# Install dependencies
pdm install
# Install development dependencies
pdm install -G dev
Running Tests
# Run all tests
pdm run test
# Run with coverage
pdm run pytest --cov=qwq_tag tests/
# Run specific test file
pdm run pytest tests/test_qwq_tag.py
Code Quality
# Format code
pdm run fix
# Check code quality
pdm run check
Available Scripts
pdm run test- Run the test suitepdm run fix- Auto-fix code formatting and linting issuespdm run check- Check code formatting and linting without making changes
Contributing
Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.
Development Workflow
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Make your changes
- Add tests for your changes
- Run the test suite (
pdm run test) - Check code quality (
pdm run check) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
Metadata
Release files for qwq-tag 0.1.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| qwq_tag-0.1.2.tar.gz | 10.7 kB | Without provenance | Details for qwq_tag-0.1.2.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| qwq_tag-0.1.2-py3-none-any.whl | Python 3 | none | any | Details for qwq_tag-0.1.2-py3-none-any.whl |
Total release size: 15.3 kB
Release files / qwq_tag-0.1.2.tar.gz
| Download URL | qwq_tag-0.1.2.tar.gz |
|---|---|
| Size | 10.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
e5c0d89de168a5b0057c25dd9a6ad00ae6bfc7ea488baa2ecb217cd0e97be84d
|
|
BLAKE2b-256 checksum How to use checksums |
1b2c81fc7afeb777a017dae72ae536005645b630c5249e9a31e9f50ede274990
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
pdm/2.25.6 CPython/3.13.5 Linux/6.11.0-1018-azure
|
Release files / qwq_tag-0.1.2-py3-none-any.whl
| Download URL | qwq_tag-0.1.2-py3-none-any.whl |
|---|---|
| Size | 4.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
c8dada889c92101ad14dbdae366d9bb31fb080f9f38d9daeaa66b1b4b9e2a79d
|
|
BLAKE2b-256 checksum How to use checksums |
d154e3d4e4e5898e6a976236ad8ec6e963664aec52f4ffe41b2fbafcbb32d725
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
pdm/2.25.6 CPython/3.13.5 Linux/6.11.0-1018-azure
|
Security for qwq-tag 0.1.2
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.