1

I'm wondering if anyone knows how to build an XML file, dynamically from a list of classes?

The classes contains public variables, and look like this.

class node {
    public $elementname;
}

I do note that some of the classes are named the same as variables, and in this case, the node would be a subnode element of a node:

class data {
   public $dataaset;
}

class dataset {
    public $datasetint;
}

would be:

 <data>
  <dataset>datasetint</dataset>
 </data>

Maybe something in SimpleXML or something?

1
  • class $dataset ? Don't think so. Commented Oct 9, 2012 at 14:22

1 Answer 1

7

The only solution i can think of linking 2 or more unrelated class is using Annotations.

Annotations is not supported by default in PHP but currently in RFC (Request for Comments: Class Metadata) but bending the time is supported or rejected you can create yours using ReflectionClass & Comments functionality

Example If you have 3 classes like this

class Data {
    /**
     *
     * @var Cleaner
     */
    public $a;
    /**
     *
     * @var Extraset
     */
    public $b;
    public $runMe;

    function __construct() {
        $this->runMe = new stdClass();
        $this->runMe->action = "RUN";
        $this->runMe->name = "ME";
    }
}
class Cleaner {
    public $varInt = 2;
    public $varWelcome = "Hello World";

    /**
     *
     * @var Extraset
     */
    public $extra;
}
class Extraset {
    public $boo = "This is Crazy";
    public $far = array(1,2,3);
}

Then you can run a code like this

$class = "Data";
$xml = new SimpleXMLElement("<$class />");
getVariablesXML($class, $xml);
header("Content-Type: text/xml");
$xml->asXML('data.xml');
echo $xml->asXML();

Output

<?xml version="1.0"?>
<Data>
  <Cleaner name="a">
    <varInt type="integer">2</varInt>
    <varWelcome type="string">Hello World</varWelcome>
    <Extraset name="extra">
      <boo type="string">This is Crazy</boo>
      <far type="serialized">a:3:{i:0;i:1;i:1;i:2;i:2;i:3;}</far>
    </Extraset>
  </Cleaner>
  <Extraset name="b">
    <boo type="string">This is Crazy</boo>
    <far type="serialized">a:3:{i:0;i:1;i:1;i:2;i:2;i:3;}</far>
  </Extraset>
  <runMe type="serialized">O:8:"stdClass":2:{s:6:"action";s:3:"RUN";s:4:"name";s:2:"ME";}</runMe>
</Data>

Function Used

function getVariablesXML($class, SimpleXMLElement $xml) {
    $reflect = new ReflectionClass($class);
    foreach ( $reflect->getProperties(ReflectionProperty::IS_PUBLIC) as $property ) {
        $propertyReflect = $reflect->getProperty($property->getName());
        preg_match("/\@var (.*)/", $propertyReflect->getDocComment(), $match);
        $match and $match = trim($match[1]);
        if (empty($match)) {
            $value = $property->getValue(new $class());
            if (is_object($value) || is_array($value)) {
                $type = "serialized";
                $value = serialize($value);
            } else {
                $type = gettype($value);
            }
            $child = $xml->addChild($property->getName(), $value);
            $child->addAttribute("type", $type);
        } else {
            $child = $xml->addChild($match);
            $child->addAttribute("name", $property->getName());
            if (class_exists($match)) {
                getVariablesXML($match, $child);
            }
        }
    }
}
Sign up to request clarification or add additional context in comments.

7 Comments

Exactly my thoughts. But while I was still forming the idea, you provided the working code :) Impressive
@Vafliik am sure it can be improved on ... let me give it a try
@Vafliik i made it recursive ... unlimited level
Hi, I just need to note that there are loads of classes, so I wouldn't be in a position to write each one out, though I suppose that I could use an array of the classes, which I have?
@Shamil you can get the array of classes by get_declared_classes(). But that will include also internal classes, so during the array iteration do a check if the class is user defined by ReflectionClass::isUserDefined. Then you may process it as Baba sugests...
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.