Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions .github/FUNDING.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1 @@
# These are supported funding model platforms

github: byjg
3 changes: 2 additions & 1 deletion .github/workflows/phpunit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,16 @@ jobs:
strategy:
matrix:
php-version:
- "8.4"
- "8.3"
- "8.2"
- "8.1"

steps:
- uses: actions/checkout@v4
- run: composer install
- run: ./vendor/bin/phpunit --stderr
- run: ./vendor/bin/psalm
- run: ./vendor/bin/phpunit

Documentation:
if: github.ref == 'refs/heads/master'
Expand Down
35 changes: 35 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "Debug current Script in Console",
"type": "php",
"request": "launch",
"program": "${file}",
"cwd": "${fileDirname}",
"port": 9003,
"runtimeArgs": [
"-dxdebug.start_with_request=yes"
],
"env": {
"XDEBUG_MODE": "debug,develop",
"XDEBUG_CONFIG": "client_port=${port}"
}
},
{
"name": "PHPUnit Debug",
"type": "php",
"request": "launch",
"program": "${workspaceFolder}/vendor/bin/phpunit",
"cwd": "${workspaceFolder}",
"port": 9003,
"runtimeArgs": [
"-dxdebug.start_with_request=yes"
],
"env": {
"XDEBUG_MODE": "debug,develop",
"XDEBUG_CONFIG": "client_port=${port}"
}
}
]
}
86 changes: 73 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,34 +1,95 @@
# XmlUtil

[![Build Status](https://github.com/byjg/php-xmlutil/actions/workflows/phpunit.yml/badge.svg?branch=master)](https://github.com/byjg/php-xmlutil/actions/workflows/phpunit.yml)
[![Opensource ByJG](https://img.shields.io/badge/opensource-byjg-success.svg)](http://opensource.byjg.com)
[![GitHub source](https://img.shields.io/badge/Github-source-informational?logo=github)](https://github.com/byjg/php-xmlutil/)
[![GitHub license](https://img.shields.io/github/license/byjg/php-xmlutil.svg)](https://opensource.byjg.com/opensource/licensing.html)
[![GitHub release](https://img.shields.io/github/release/byjg/php-xmlutil.svg)](https://github.com/byjg/php-xmlutil/releases/)

A utility class to make it easy work with XML in PHP
# PHP XML Util

A powerful and intuitive PHP library for working with XML documents. This utility makes XML manipulation, querying,
and conversion simple and straightforward in PHP.

## Overview

PHP XML Util provides a comprehensive set of tools for XML manipulation in PHP applications. It simplifies common
XML operations with an intuitive API, allowing developers to create, modify, query, and validate XML documents
with minimal code.

The library is designed to be lightweight yet powerful, offering features that go beyond
PHP's built-in XML functionality while maintaining a clean and easy-to-use interface.

## Examples
## Key Features

- [Create a new XML Document using the API](docs/using-api.md)
- [Working with namespaces](docs/namespaces.md)
- [Query a XMLDocument](docs/query-document.md)
- [Convert any model to XML](docs/convert-model-xml.md)
- [Use Attributes to help in the conversion](docs/convert-model-xml-withattributes.md)
- [Clean an XML document removing specific tags](docs/clean-document.md)
- **Simple XML Creation API** - Create and manipulate XML documents programmatically with an intuitive API
- **XPath Querying** - Easily query and navigate XML documents using XPath expressions
- **PHP Model ↔ XML Conversion** - Seamlessly convert between PHP objects and XML representations
- **Attribute-Based Mapping** - Use PHP attributes to control XML serialization behavior
- **Namespace Support** - Full support for XML namespaces in all operations
- **Document Cleaning** - Selectively remove specific tags from XML documents
- **XML Validation** - Validate XML documents against schemas
- **File Handling** - Convenient methods for loading and saving XML from/to files

## Install
## Quick Example

```php
<?php
use ByJG\XmlUtil\XmlDocument;

// Create a new XML document
$xml = new XmlDocument('<root />');

// Build the document structure
$myNode = $xml->appendChild('mynode');
$myNode->appendChild('subnode', 'text');
$myNode->appendChild('subnode', 'more text');
$otherNode = $myNode->appendChild('othersubnode', 'other text');
$otherNode->addAttribute('attr', 'value');

// Output formatted XML
echo $xml->toString(format: true);
```

Output:
```xml
<?xml version="1.0" encoding="utf-8"?>
<root>
<mynode>
<subnode>text</subnode>
<subnode>more text</subnode>
<othersubnode attr="value">other text</othersubnode>
</mynode>
</root>
```

## Documentation

The library is fully documented with detailed guides and examples for each feature:

- [Creating XML Documents](docs/using-api.md): Learn how to create and manipulate XML documents using the API
- [Working with Namespaces](docs/namespaces.md): Guide to handling XML namespaces properly
- [Querying with XPath](docs/query-document.md): How to use XPath expressions to query XML documents
- [PHP Models to XML](docs/convert-model-xml.md): Converting PHP objects to XML and vice versa
- [Attribute-Based Mapping](docs/convert-model-xml-withattributes.md): Using PHP attributes to control XML serialization
- [Cleaning Documents](docs/clean-document.md): Removing specific tags from XML documents
- [File Operations](docs/file-handling.md): Loading and saving XML from/to files
- [XML Validation](docs/validate-document.md): Validating XML documents against schemas

## Installation

```bash
composer require "byjg/xmlutil"
```

## Running the Tests
## Running Tests

```bash
vendor/bin/phpunit
```

## License

MIT

## Dependencies

```mermaid
Expand All @@ -38,6 +99,5 @@ flowchart TD
byjg/xmlutil --> byjg/serializer
```


----
[Open source ByJG](http://opensource.byjg.com)
8 changes: 4 additions & 4 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,15 @@
"minimum-stability": "dev",
"prefer-stable": true,
"require": {
"php": ">=8.1 <8.4",
"php": ">=8.1 <8.5",
"ext-dom": "*",
"ext-libxml": "*",
"ext-simplexml": "*",
"byjg/serializer": "^5.0"
"byjg/serializer": "^5.1"
},
"require-dev": {
"phpunit/phpunit": "^9.6",
"vimeo/psalm": "^5.20"
"phpunit/phpunit": "^10.5|^11.5",
"vimeo/psalm": "^5.9|^6.2"
},
"license": "MIT"
}
70 changes: 67 additions & 3 deletions docs/clean-document.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,9 @@ sidebar_position: 6

# Clean Document

XmlUtil have a class for selectively remove specific marks (tags)
from the document or remove all marks.
XmlUtil provides a dedicated `CleanDocument` class for selectively removing specific tags or content from XML or HTML documents. This is useful for cleaning up documents before processing or display.

Example:
## Basic Usage

```php
<?php
Expand All @@ -20,3 +19,68 @@ $document
->stripTagsExcept(['img'])
->get();
```

## Available Methods

### stripAllTags()

Removes all HTML/XML tags from the document.

```php
$document = new \ByJG\XmlUtil\CleanDocument($html);
$plainText = $document->stripAllTags();
```

### stripTagsExcept(array $allowedTags)

Strips all HTML/XML tags except those specified in the array.

```php
$document = new \ByJG\XmlUtil\CleanDocument($html);
$cleanHtml = $document->stripTagsExcept(['p', 'div', 'span'])->get();
```

### removeContentByProperty(string $property)

Removes content from any tag that contains the specified property.

```php
$document = new \ByJG\XmlUtil\CleanDocument($html);
// Removes all tags containing the "style" property and their content
$cleanHtml = $document->removeContentByProperty('style')->get();
```

### removeContentByTag(string $tag, string $property = '')

Removes content from the specified tag, optionally filtering by a property.

```php
$document = new \ByJG\XmlUtil\CleanDocument($html);
// Removes all <script> tags and their content
$cleanHtml = $document->removeContentByTag('script')->get();

// Removes all <a> tags that have an "onclick" property
$cleanHtml = $document->removeContentByTag('a', 'onclick')->get();
```

### removeContentByTagWithoutProperty(string $tag, string $property)

Removes content from the specified tag that does NOT have the specified property.

```php
$document = new \ByJG\XmlUtil\CleanDocument($html);
// Removes all <a> tags that don't have an "href" property
$cleanHtml = $document->removeContentByTagWithoutProperty('a', 'href')->get();
```

### get()

Returns the cleaned document as a string.

```php
$document = new \ByJG\XmlUtil\CleanDocument($html);
// Apply cleaning operations
$document->removeContentByTag('script');
// Get the final result
$cleanHtml = $document->get();
```
60 changes: 47 additions & 13 deletions docs/convert-model-xml-withattributes.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@ sidebar_position: 5

# Convert a model to XML with Attributes

You can add PHP attributes to your model to help the EntityParser to convert the model to XML.
You can add PHP attributes to your model to help the EntityParser to convert the model to XML. This provides precise control over the XML serialization process.

Example:
```php
<?php

use ByJG\XmlUtil\EntityParser;
use ByJG\XmlUtil\XmlMapping\XmlEntity;
use ByJG\XmlUtil\XmlMapping\XmlProperty;
use ByJG\XmlUtil\Attributes\XmlEntity;
use ByJG\XmlUtil\Attributes\XmlProperty;

#[XmlEntity(
rootElementName: 'Person',
Expand Down Expand Up @@ -67,6 +67,40 @@ The output will be:
</Person>
```

## Attributes as XML Attributes

You can also map properties to XML attributes instead of elements:

```php
#[XmlEntity(rootElementName: 'Person', preserveCaseName: true)]
class PersonWithAttributes
{
#[XmlProperty(elementName: 'Name', preserveCaseName: true)]
public $name;

#[XmlProperty(isAttribute: true)]
public $id;

#[XmlProperty(isAttributeOf: 'Name')]
public $type;
}

$person = new PersonWithAttributes();
$person->name = 'John Doe';
$person->id = '12345';
$person->type = 'full';

$xml = (new EntityParser())->parse($person);
```

Output:
```xml
<?xml version="1.0" encoding="utf-8"?>
<Person id="12345">
<Name type="full">John Doe</Name>
</Person>
```

## The XmlEntity Attribute

Properties:
Expand All @@ -84,13 +118,13 @@ Properties:

Properties:

| Property | Description | Default |
|-----------------|----------------------------------------------------------------------------------------------------------|-------------------|
| `elementName` | The name of the element different from the property name. | The property name |
| `preserveCase` | Preserve the case of the element name, if false, all elements will be lowercase. | false |
| `namespaces` | The namespace of the element. Need to be an associative array with prefix as key and namespace as value. | empty |
| `isAttribute` | If the element is an attribute of the parent node instead of a node. | false |
| `isAttributeOf` | The name of the sibling node that will receive the attribute. | empty |
| `isChildOf` | The name of the sibling node that will receive the child node. | empty |
| `ignore` | If true, the property will not be parsed. | false |
| `ignoreEmpty` | If true will ignore empty strings | empty |
| Property | Description | Default |
|--------------------|----------------------------------------------------------------------------------------------------------|-------------------|
| `elementName` | The name of the element different from the property name. | The property name |
| `preserveCaseName` | Preserve the case of the element name, if false, all elements will be lowercase. | false |
| `namespaces` | The namespace of the element. Need to be an associative array with prefix as key and namespace as value. | empty |
| `isAttribute` | If the element is an attribute of the parent node instead of a node. | false |
| `isAttributeOf` | The name of the sibling node that will receive the attribute. | empty |
| `isChildOf` | The name of the sibling node that will receive the child node. | empty |
| `ignore` | If true, the property will not be parsed. | false |
| `ignoreEmpty` | If true will ignore empty strings | false |
Loading