Skip to content

Commit

Permalink
Detect <any /> element information
Browse files Browse the repository at this point in the history
  • Loading branch information
veewee committed Aug 30, 2024
1 parent 51558f6 commit 3ae23e7
Show file tree
Hide file tree
Showing 4 changed files with 254 additions and 0 deletions.
65 changes: 65 additions & 0 deletions src/Schema/Element/Any/Any.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<?php

declare(strict_types=1);

namespace GoetasWebservices\XML\XSDReader\Schema\Element\Any;

use GoetasWebservices\XML\XSDReader\Schema\Element\ElementItem;
use GoetasWebservices\XML\XSDReader\Schema\Element\InterfaceSetMinMax;
use GoetasWebservices\XML\XSDReader\Schema\Element\MinMaxTrait;
use GoetasWebservices\XML\XSDReader\Schema\Schema;
use GoetasWebservices\XML\XSDReader\Schema\SchemaItem;
use GoetasWebservices\XML\XSDReader\Schema\SchemaItemTrait;

/**
* Represents https://www.w3schools.com/xml/el_any.asp.
*/
class Any implements SchemaItem, ElementItem, InterfaceSetMinMax
{
use MinMaxTrait;
use SchemaItemTrait;

protected ?string $namespace = null;
protected ProcessContents $processContents = ProcessContents::Strict;
protected ?string $id = null;

public function __construct(Schema $schema)
{
$this->schema = $schema;
}

public function getName(): string
{
return 'any';
}

public function getNamespace(): ?string
{
return $this->namespace;
}

public function setNamespace(?string $namespace): void
{
$this->namespace = $namespace;
}

public function getProcessContents(): ProcessContents
{
return $this->processContents;
}

public function setProcessContents(ProcessContents $processContents): void
{
$this->processContents = $processContents;
}

public function getId(): ?string
{
return $this->id;
}

public function setId(?string $id): void
{
$this->id = $id;
}
}
15 changes: 15 additions & 0 deletions src/Schema/Element/Any/ProcessContents.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

namespace GoetasWebservices\XML\XSDReader\Schema\Element\Any;

enum ProcessContents: string
{
case Strict = 'strict';
case Lax = 'lax';
case Skip = 'skip';

public static function default(): self
{
return self::Strict;
}
}
61 changes: 61 additions & 0 deletions src/SchemaReader.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
use GoetasWebservices\XML\XSDReader\Schema\Attribute\Group as AttributeGroup;
use GoetasWebservices\XML\XSDReader\Schema\CustomAttribute;
use GoetasWebservices\XML\XSDReader\Schema\Element\AbstractElementSingle;
use GoetasWebservices\XML\XSDReader\Schema\Element\Any\Any;
use GoetasWebservices\XML\XSDReader\Schema\Element\Any\ProcessContents;
use GoetasWebservices\XML\XSDReader\Schema\Element\Choice;
use GoetasWebservices\XML\XSDReader\Schema\Element\Element;
use GoetasWebservices\XML\XSDReader\Schema\Element\ElementContainer;
Expand Down Expand Up @@ -499,6 +501,15 @@ private function loadSequenceChildNode(
$elementContainer
);
break;
case 'any':
$this->loadSequenceChildNodeLoadAny(
$elementContainer,
$node,
$childNode,
$max,
$min
);
break;
}
}

Expand Down Expand Up @@ -535,6 +546,26 @@ private function loadSequenceChildNodeLoadElement(
$elementContainer->addElement($element);
}

private function loadSequenceChildNodeLoadAny(
ElementContainer $elementContainer,
\DOMElement $node,
\DOMElement $childNode,
?int $max,
?int $min
): void {
$schema = $elementContainer->getSchema();
$element = $this->createAnyElement($schema, $childNode);

if (null !== $min) {
$element->setMin($min);
}

if (null !== $max && 1 < $max) {
$element->setMax($max);
}
$elementContainer->addElement($element);
}

private function resolveSubstitutionGroup(
Schema $schema,
\DOMElement $node,
Expand Down Expand Up @@ -1489,6 +1520,36 @@ private function fillElement(AbstractElementSingle $element, \DOMElement $node):
$element->setCustomAttributes($this->loadCustomAttributesForElement($element, $node));
}

private function createAnyElement(Schema $schema, \DOMElement $node): Any
{
$element = new Any($schema);
$this->fillAnyElement($element, $node);

return $element;
}

private function fillAnyElement(Any $element, \DOMElement $node): void
{
self::maybeSetMax($element, $node);
self::maybeSetMin($element, $node);

if ($node->hasAttribute('id')) {
$element->setId($node->getAttribute('id'));
}

if ($node->hasAttribute('namespace')) {
$element->setNamespace($node->getAttribute('namespace'));
}

if ($node->hasAttribute('processContents')) {
$element->setProcessContents(
ProcessContents::tryFrom($node->getAttribute('processContents')) ?? ProcessContents::default()
);
}

$element->setDoc($this->getDocumentation($node));
}

private function addAttributeFromAttributeOrRef(
BaseComplexType $type,
\DOMElement $childNode,
Expand Down
113 changes: 113 additions & 0 deletions tests/AnyTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
<?php

declare(strict_types=1);

use GoetasWebservices\XML\XSDReader\Schema\Element\Any\Any;
use GoetasWebservices\XML\XSDReader\Schema\Element\Any\ProcessContents;
use GoetasWebservices\XML\XSDReader\Schema\Type\ComplexType;
use GoetasWebservices\XML\XSDReader\Tests\BaseTest;

class AnyTest extends BaseTest
{
public function testBase(): void
{
$schema = $this->reader->readString(
'
<xs:schema targetNamespace="http://www.example.com" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="customerData">
<xs:complexType>
<xs:sequence>
<xs:any />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>'
);

$myElement = $schema->findElement('customerData', 'http://www.example.com');
$myType = $myElement->getType();

self::assertInstanceOf(ComplexType::class, $myType);

$elements = $myType->getElements();

self::assertCount(1, $elements);
self::assertInstanceOf(Any::class, $any = $elements[0]);

self::assertSame($schema, $any->getSchema());
self::assertSame('any', $any->getName());
self::assertNull($any->getNamespace());
self::assertSame(ProcessContents::Strict, $any->getProcessContents());
self::assertNull($any->getId());
self::assertSame(1, $any->getMin());
self::assertSame(1, $any->getMax());
self::assertSame('', $any->getDoc());
}

public function testAllArgsSet(): void
{
$schema = $this->reader->readString(
'
<xs:schema targetNamespace="http://www.example.com" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="customerData">
<xs:complexType>
<xs:sequence>
<xs:any id="hello" minOccurs="0" maxOccurs="2" processContents="lax" namespace="##any">
<xs:annotation>
<xs:documentation>Any description</xs:documentation>
</xs:annotation>
</xs:any>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>'
);

$myElement = $schema->findElement('customerData', 'http://www.example.com');
$myType = $myElement->getType();

self::assertInstanceOf(ComplexType::class, $myType);

$elements = $myType->getElements();

self::assertCount(1, $elements);
self::assertInstanceOf(Any::class, $any = $elements[0]);

self::assertSame($schema, $any->getSchema());
self::assertSame('any', $any->getName());
self::assertSame('##any', $any->getNamespace());
self::assertSame(ProcessContents::Lax, $any->getProcessContents());
self::assertSame('hello', $any->getId());
self::assertSame(0, $any->getMin());
self::assertSame(2, $any->getMax());
self::assertSame('Any description', $any->getDoc());
}

public function testCombinationWithOtherElements(): void
{
$schema = $this->reader->readString(
'
<xs:schema targetNamespace="http://www.example.com" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="customerData">
<xs:complexType>
<xs:sequence>
<xs:element name="firstName" type="xs:string" />
<xs:element name="lastName" type="xs:string" />
<xs:any id="hello" minOccurs="0" maxOccurs="2" processContents="lax" namespace="##any" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>'
);

$myElement = $schema->findElement('customerData', 'http://www.example.com');
$myType = $myElement->getType();

self::assertInstanceOf(ComplexType::class, $myType);

$elements = $myType->getElements();

self::assertCount(3, $elements);
self::assertInstanceOf(Any::class, $any = $elements[2]);
}
}

0 comments on commit 3ae23e7

Please sign in to comment.