MYMONDAY.ai
서비스스튜디오도구데이터·포맷73CSS 생성기19색상·이미지10인코딩·보안10웹·SEO11개발·데브옵스10파일·내보내기18계산기6가이드

XML PHP 클래스 변환기

샘플 XML에서 타입이 지정된 프로모션 프로퍼티와 배열 변환 메서드가 있는 PHP 8 클래스를 만듭니다.

  • 브라우저에서 처리
  • 가입 없음
  • 무료

도구 작업 공간

예제

옵션

XML → 데이터 매핑

속성은 이 문자로 시작하는 키가 되어 id="1"은 @id가 됩니다. 비우면 속성 이름 그대로 씁니다.

속성이나 자식 요소와 함께 있는 텍스트는 이 키에 담습니다.

끄면 <item>이 하나일 땐 객체, 여러 개일 땐 배열이 됩니다. 켜면 개수와 상관없이 구조가 같습니다.

끄면 모든 값이 문자열로 남습니다. 켜면 true/false, 정수, 소수는 해당 타입이 되고 007이나 긴 ID는 문자열로 둡니다.

XML 입력

21줄491byte

결과

⌘/Ctrl + Enter로 복사
결과 · Payload.php
<?php

declare(strict_types=1);

final class Payload
{
    public function __construct(
        public PayloadOrder $order,
    ) {}

    /** @param array<string, mixed> $data */
    public static function fromArray(array $data): self
    {
        return new self(
            order: PayloadOrder::fromArray($data['order']),
        );
    }

    /** @return array<string, mixed> */
    public function toArray(): array
    {
        return [
            'order' => $this->order->toArray(),
        ];
    }
}

final class PayloadOrder
{
    public function __construct(
        public int $id,
        public string $status,
        public PayloadOrderCustomer $customer,
        public PayloadOrderItems $items,
        public float $total,
        public string $shippedAt,
        public string $tracking,
    ) {}

    /** @param array<string, mixed> $data */
    public static function fromArray(array $data): self
    {
        return new self(
            id: $data['@id'],
            status: $data['@status'],
            customer: PayloadOrderCustomer::fromArray($data['customer']),
            items: PayloadOrderItems::fromArray($data['items']),
            total: $data['total'],
            shippedAt: $data['shipped_at'],
            tracking: $data['tracking'],
        );
    }

    /** @return array<string, mixed> */
    public function toArray(): array
    {
        return [
            '@id' => $this->id,
            '@status' => $this->status,
            'customer' => $this->customer->toArray(),
            'items' => $this->items->toArray(),
            'total' => $this->total,
            'shipped_at' => $this->shippedAt,
            'tracking' => $this->tracking,
        ];
    }
}

final class PayloadOrderCustomer
{
    public function __construct(
        public int $id,
        public bool $vip,
        public string $name,
        public string $email,
    ) {}

    /** @param array<string, mixed> $data */
    public static function fromArray(array $data): self
    {
        return new self(
            id: $data['@id'],
            vip: $data['@vip'],
            name: $data['name'],
            email: $data['email'],
        );
    }

    /** @return array<string, mixed> */
    public function toArray(): array
    {
        return [
            '@id' => $this->id,
            '@vip' => $this->vip,
            'name' => $this->name,
            'email' => $this->email,
        ];
    }
}

final class PayloadOrderItems
{
    public function __construct(
        /** @var list<PayloadOrderItemsItem> */
        public array $item,
    ) {}

    /** @param array<string, mixed> $data */
    public static function fromArray(array $data): self
    {
        return new self(
            item: array_map(static fn ($v) => PayloadOrderItemsItem::fromArray($v), $data['item']),
        );
    }

    /** @return array<string, mixed> */
    public function toArray(): array
    {
        return [
            'item' => array_map(static fn ($v) => $v->toArray(), $this->item),
        ];
    }
}

final class PayloadOrderItemsItem
{
    public function __construct(
        public string $sku,
        public int $qty,
        public string $name,
        public float $price,
    ) {}

    /** @param array<string, mixed> $data */
    public static function fromArray(array $data): self
    {
        return new self(
            sku: $data['@sku'],
            qty: $data['@qty'],
            name: $data['name'],
            price: $data['price'],
        );
    }

    /** @return array<string, mixed> */
    public function toArray(): array
    {
        return [
            '@sku' => $this->sku,
            '@qty' => $this->qty,
            'name' => $this->name,
            'price' => $this->price,
        ];
    }
}
타입5
크기3.7kB

이 도구는 샘플 XML에 대한 PHP 클래스를 씁니다. 먼저 모든 XML 변환기가 공유하는 규칙으로 XML을 데이터로 매핑하고, 클래스는 그 데이터가 json_decode($json, true) 뒤에 갖는 모양, 곧 문자열 키를 가진 중첩 배열을 모델링합니다. 속성이나 자식이 있는 요소는 생성자 프로퍼티 프로모션을 쓰는 final class가 됩니다.

모든 클래스에 fromArray(array $data): self와 toArray(): array가 붙습니다. 배열 키는 데이터 키 그대로여서 속성 sku는 $data['@sku']로 읽고 프로퍼티 이름은 $sku입니다. 코드는 declare(strict_types=1);로 시작하고 이름 있는 인수 때문에 PHP 8.0 이상이 필요하며, 실제로는 8.1 이상을 대상으로 합니다.

입력은 엄격한 XML 1.0 파서가 읽고 오류에는 정확한 행과 열이 표시되며 한도는 20 MiB입니다. 문서는 브라우저 안에서 처리됩니다.

사용 방법

  1. XML 붙여넣기

    문서를 붙여 넣거나 예제를 엽니다. 입력하는 동안 PHP 코드가 다시 생성됩니다.

  2. 매핑 설정

    XML 데이터 매핑 패널에서 속성 접두사, 텍스트 키, 항상 배열, 숫자 추론을 바꿉니다. 추론을 끄면 모든 프로퍼티가 string입니다.

  3. 클래스 이름 정하기

    루트 클래스 이름(기본 Payload)과 선택 사항인 네임스페이스를 입력합니다. 네임스페이스는 declare 아래에 namespace ...;로 쓰입니다.

  4. 결과 읽기

    중첩 클래스는 루트 뒤에 옵니다. 선택 프로퍼티는 null 기본값을 가진 ?type이며 생성자 맨 끝에 놓입니다.

  5. 복사 또는 다운로드

    코드를 복사하거나 루트 클래스 이름의 Payload.php로 내려받습니다.

작동 원리

데이터 키와 PHP 타입

PHP에는 int, float, bool, string이 있어 정수는 모두 int, 소수는 모두 float입니다. PHP는 요소 타입을 선언할 수 없으므로 리스트는 array에 @var list<...> 문서 주석을 붙여 표현합니다.

XMLPHP 프로퍼티배열에서 읽는 방식
<name>Ada</name>public string $name$data['name']
id="7"public int $id$data['@id']
<price>19.5</price>public float $price$data['price']
<ok>true</ok>public bool $ok$data['ok']
반복되는 <item>public array $itemarray_map으로 PayloadItem::fromArray
일부 item에만 있는 키public ?int $qty = null$data['@qty'] ?? null
<v>1</v><v>a</v>/** @var list<mixed> */ array그대로 복사

순서, 선택 값, strict types

PHP는 필수 매개변수를 선택 매개변수 뒤에 둘 수 없으므로 선택 프로퍼티는 생성자 맨 끝으로 옮겨집니다. 그래서 프로퍼티 순서가 문서 순서와 늘 같지는 않지만, fromArray는 이름 있는 인수를 쓰므로 상관없습니다.

strict_types가 켜져 있어 int 자리에 문자열이 오면 TypeError가 납니다. 타입을 샘플에 맞춰 엄격하게 잡는 이유이고 007이 string 프로퍼티로 남는 이유이기도 합니다. toArray는 선택 프로퍼티가 null이어도 키를 씁니다.

final class PayloadOrderItem
{
    public function __construct(
        public string $sku,
        public string $text,
        public ?int $qty = null,
    ) {}
}

자식 하나일 때와 리스트

<item>이 하나면 프로퍼티는 중첩 객체이고 자식 배열에 fromArray를 호출합니다. 자식 요소는 항상 배열로 옵션을 켜면 하나뿐이어도 객체 리스트가 되어 array_map이 하나든 여럿이든 실패하지 않습니다.

실제 예시

반복 항목이 있는 주문
입력
<order id="1042"><item sku="A1" qty="1">Pen</item><item sku="B7">Ink</item></order>
출력
<?php

declare(strict_types=1);

final class Payload
{
    public function __construct(
        public PayloadOrder $order,
    ) {}

    /** @param array<string, mixed> $data */
    public static function fromArray(array $data): self
    {
        return new self(
            order: PayloadOrder::fromArray($data['order']),
        );
    }

    /** @return array<string, mixed> */
    public function toArray(): array
    {
        return [
            'order' => $this->order->toArray(),
        ];
    }
}

final class PayloadOrder
{
    public function __construct(
        public int $id,
        /** @var list<PayloadOrderItem> */
        public array $item,
    ) {}

    /** @param array<string, mixed> $data */
    public static function fromArray(array $data): self
    {
        return new self(
            id: $data['@id'],
            item: array_map(static fn ($v) => PayloadOrderItem::fromArray($v), $data['item']),
        );
    }

    /** @return array<string, mixed> */
    public function toArray(): array
    {
        return [
            '@id' => $this->id,
            'item' => array_map(static fn ($v) => $v->toArray(), $this->item),
        ];
    }
}

final class PayloadOrderItem
{
    public function __construct(
        public string $sku,
        public string $text,
        public ?int $qty = null,
    ) {}

    /** @param array<string, mixed> $data */
    public static function fromArray(array $data): self
    {
        return new self(
            sku: $data['@sku'],
            qty: $data['@qty'] ?? null,
            text: $data['#text'],
        );
    }

    /** @return array<string, mixed> */
    public function toArray(): array
    {
        return [
            '@sku' => $this->sku,
            '@qty' => $this->qty,
            '#text' => $this->text,
        ];
    }
}

qty는 선택이라 null 기본값의 ?int이며 생성자 끝으로 이동합니다. fromArray는 @ 접두사가 붙은 속성 키를 읽습니다.

네임스페이스와 하이픈이 있는 이름
입력
<doc xml:lang="en" data-id="5"><title>Hi</title></doc>
출력
<?php

declare(strict_types=1);

final class Payload
{
    public function __construct(
        public PayloadDoc $doc,
    ) {}

    /** @param array<string, mixed> $data */
    public static function fromArray(array $data): self
    {
        return new self(
            doc: PayloadDoc::fromArray($data['doc']),
        );
    }

    /** @return array<string, mixed> */
    public function toArray(): array
    {
        return [
            'doc' => $this->doc->toArray(),
        ];
    }
}

final class PayloadDoc
{
    public function __construct(
        public string $xmlLang,
        public int $dataId,
        public string $title,
    ) {}

    /** @param array<string, mixed> $data */
    public static function fromArray(array $data): self
    {
        return new self(
            xmlLang: $data['@xml:lang'],
            dataId: $data['@data-id'],
            title: $data['title'],
        );
    }

    /** @return array<string, mixed> */
    public function toArray(): array
    {
        return [
            '@xml:lang' => $this->xmlLang,
            '@data-id' => $this->dataId,
            'title' => $this->title,
        ];
    }
}

프로모션 프로퍼티는 $xmlLang, $dataId이고 배열 키에는 '@xml:lang', '@data-id'가 남습니다.

타입 추론을 끈 경우
입력
<p><zip>02134</zip><qty>3</qty><price>19.5</price><ok>true</ok><note><![CDATA[42]]></note></p>
출력
<?php

declare(strict_types=1);

final class Payload
{
    public function __construct(
        public PayloadP $p,
    ) {}

    /** @param array<string, mixed> $data */
    public static function fromArray(array $data): self
    {
        return new self(
            p: PayloadP::fromArray($data['p']),
        );
    }

    /** @return array<string, mixed> */
    public function toArray(): array
    {
        return [
            'p' => $this->p->toArray(),
        ];
    }
}

final class PayloadP
{
    public function __construct(
        public string $zip,
        public string $qty,
        public string $price,
        public string $ok,
        public string $note,
    ) {}

    /** @param array<string, mixed> $data */
    public static function fromArray(array $data): self
    {
        return new self(
            zip: $data['zip'],
            qty: $data['qty'],
            price: $data['price'],
            ok: $data['ok'],
            note: $data['note'],
        );
    }

    /** @return array<string, mixed> */
    public function toArray(): array
    {
        return [
            'zip' => $this->zip,
            'qty' => $this->qty,
            'price' => $this->price,
            'ok' => $this->ok,
            'note' => $this->note,
        ];
    }
}

추론을 끄면 qty, price, ok가 모두 public string이 됩니다. 데이터 공급을 통제할 수 없을 때 가장 안전한 모델입니다.

자주 하는 실수

  • json_decode에 연관 배열 플래그가 필요합니다

    fromArray는 배열을 기대합니다. json_decode($json, true)로 호출하세요. true가 없으면 stdClass 객체가 나와 array $data에서 TypeError가 납니다.

  • 필수 키 누락은 검사하지 않습니다

    fromArray는 입력을 검증하지 않습니다. 필수 키가 없으면 정의되지 않은 배열 키 경고가 나고 이어서 생성자에서 타입 오류가 납니다.

  • strict types에서의 int와 float

    샘플에서 19였던 값은 int가 되고, 나중에 19.5가 오면 TypeError가 납니다. 소수부가 있는 예를 넣거나 추론을 끄세요.

  • SimpleXML용이 아닙니다

    SimpleXML과 DOM은 @sku 같은 키가 아니라 요소와 속성을 제공합니다. 먼저 변환된 JSON으로 바꾸세요.

자주 묻는 질문

출력에는 어떤 PHP 버전이 필요한가요?

생성자 프로모션과 이름 있는 인수 때문에 PHP 8.0이 필요하고, list<...> 문서 주석은 PHPStan, Psalm 같은 PHP 8.1용 도구에 잘 맞습니다.

프로퍼티 이름이 왜 $xmlLang인가요?

키 @xml:lang은 올바른 변수 이름이 아니기 때문입니다. 프로퍼티는 lowerCamelCase이고 fromArray와 toArray는 정확한 키를 씁니다.

XML을 이 클래스로 읽으려면 어떻게 하나요?

XML to JSON 변환기로 변환된 JSON을 만들고 json_decode($json, true)로 디코딩한 뒤 Payload::fromArray를 호출하세요.

toArray는 선택 키를 어떻게 처리하나요?

값이 없으면 null로 써서 왕복 변환에도 키가 유지됩니다. 빼고 싶다면 array_filter로 걸러 내세요.

네임스페이스를 추가할 수 있나요?

네. 네임스페이스 옵션에 App\Models 같은 값을 적으면 declare 뒤에 한 번 쓰입니다.

업로드되는 것이 있나요?

없습니다. 파싱과 생성이 페이지 안에서 실행되고 XML은 기기에 남습니다.

마지막 업데이트: