xml icon indicating copy to clipboard operation
xml copied to clipboard

Getting attributes and values from an element not working as expected

Open tacman opened this issue 5 years ago • 0 comments

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

tacman avatar Dec 21 '20 19:12 tacman