Skip to content

Getting attributes and values from an element not working as expected #198

Open
@tacman

Description

@tacman

What an excellent library, thanks for sharing this.

It is mostly working for me, but I'm struggling how to get an element that has a #text value and attributes, e.g.

  <elementSets>
    <settings>
      <setting name="fieldWidth">70</setting>
      <setting name="fieldHeight">1</setting>
    </settings>
   ...

I've overwritten mapValueObject to get the attributes, but must be doing something wrong:

    // from the parent
    public function mapValueObject(string $elementName, string $className)
    {

        list($namespace) = self::parseClarkNotation($elementName);

        $this->elementMap[$elementName] = function (Reader $reader) use ($className, $namespace) {

            $properties = [];
// if I call this, then $o comes back with the #text and is what I want, but I need the attributes to figure out the context.  If I add this line, I can't figure out how to get the actual value.
//            $properties = $reader->parseAttributes(); 
            $o = \Sabre\Xml\Deserializer\valueObject($reader, $className, $namespace);

// hacking away here.
            if ($className == ProfileSetting::class) {
                if ($reader->name === '#text') {
                    $_value = $reader->value;
                }
                dump($o, $properties, $className, $reader->name, $_value);
            }


            if (count($properties)) {
                if (array_key_exists('fieldWidth', $properties)) {
                    dd($properties, $o);
                }
                $o->setAttributes($properties);
            }

//            foreach($properties as $key=>$value) {
//                $o->$key = $value;
//                if (isset($o->{$key})) {
//                    $o->$key = $value;
//                }
//            }

            return $o;

        };
        $this->classMap[$className] = function (Writer $writer, $valueObject) use ($namespace) {
            return \Sabre\Xml\Serializer\valueObject($writer, $valueObject, $namespace);
        };
        $this->valueObjectMap[$className] = $elementName;
    }

So I should be able to use in my class

  $this->mapValueObject($ca . 'setting', ProfileSetting::class);

I'd like to suggest that this is such a common situation that perhaps you could make that the default, or at least the example. You could put the attributes in a '@attributes' property (like SimpleXML), or some convention like $_, which is probably what I'll do when I figure this out.

Thanks!

Tac

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions