简体   繁体   中英

How to add a Nested xml element

I'm on the home stretch of putting together an xml property listing feed that a syndicator will use to publish our listings.

I'm using Cakephp, but not using the Cakephp xml tools. Just couldn't get the output formatted how I need it.

So I have a very simple query. (many fields not included here for clarity)

$sql = "select 
        Listing.id as PropertyId, 
        Listing.address as StreetAddress,
        Listing.title as Caption,
        Listing.description as Description
        from properties as Listing
        limit 2";

$properties = $this->Property->query($sql);

Then doing a little cleansing and adding some attributes which are not in the db.

for($i=0;$i<count($properties);$i++){
     $properties[$i]['Listing']['StreetAddress'] = '<![CDATA['.$properties[$i]['Listing']['StreetAddress'].']]>';
     $properties[$i]['Listing']['DescriptionLang'] = "x";     
     $properties[$i]['Listing']['Caption'] = '<![CDATA['.$properties[$i]['Listing']['Caption'].']]>';
     $properties[$i]['Listing']['Description'] = '<![CDATA['.$properties[$i]['Listing']['Description'].']]>';
}

I'm using this function to proccess the array...

header("Content-type: text/xml; charset=utf-8");
$domtree = new DOMDocument('1.0', 'UTF-8');
$xmlRoot = $domtree->createElement("Listings");
$xmlRoot = $domtree->appendChild($xmlRoot);
foreach($properties as $p){
     foreach ($p as $key=>$value){
         $currentElement= $domtree->createElement($key);
         $currentElement= $xmlRoot->appendChild($currentElement);
         if(is_array($value))
         {
             foreach ($value as $k=>$v)
             {
                 $currentElement->appendChild($domtree->createElement($k,$v));
             }
         }
     }
 }   
 echo $domtree->saveXML();
 exit;

Creates this, which is nearly perfect:

 <Listings>
  <Listing>
    <PropertyId>2</PropertyId>
    <StreetAddress><![CDATA[243 E 7th Ave]]></StreetAddress>
    <Caption><![CDATA[Wholesale Deal]]></Caption>
    <Description><![CDATA[]]></Description>
    <DescriptionLang>x</DescriptionLang>
  </Listing>
  <Listing>
    <PropertyId>3</PropertyId>
    <StreetAddress><![CDATA[3724 W Glenn Dr]]></StreetAddress>
    <Caption><![CDATA[Wholesale Deal]]></Caption>
    <Description><![CDATA[]]></Description>
    <DescriptionLang>x</DescriptionLang>
   </Listing>
  </Listings>

The output looks great... except I need to do two things.

1.) The tag for DescriptionLang needs to be as follows, but causes problems...

<DescriptionLang value="en">

It doesn't like the space or the quotes. For the quotes I tried this...

&quot; 

But that goes over like a fart in church as well.

Update: The xml spec does not allow spaces. So I'm checking with the syndicator to see if he can tell me how they get away with something that can't be done.

2.) But the big one is that the Caption and Description elements need to be nested within the DescriptionLang element like so...

<DescriptionLang value="en">
    <Caption><![CDATA[ captionhere ]]></Caption>
    <Description><![CDATA[ descriptionhere ]]></Description> 
</DescriptionLang>

I've tried more crazy stuff that I can include here. Seems like I should be able to just add another level in the cleansing step, but no.

Sure could use a little guidance here.

I finished this project so thought I would share the final xml array builder. In the data spec there were just few elements that needed some attibutes set, or nested elements. I have no idea whether there is an easier way to do this as this was my first attempt at anything xml. Works perfect for my needs.

header("Content-type: text/xml; charset=utf-8");
        $domtree = new DOMDocument('1.0', 'UTF-8');
        $xmlRoot = $domtree->createElement("Listings");
        $xmlRoot = $domtree->appendChild($xmlRoot);
        foreach($properties as $p){
            foreach ($p as $key=>$value){
                $currentElement= $domtree->createElement($key);
                $currentElement= $xmlRoot->appendChild($currentElement);
                if(is_array($value))
                {
                    foreach ($value as $k=>$v)
                    {
                        if(!in_array($k,array('Caption','Description','DetailsURL','PhotoURL')))
                        $level = $currentElement->appendChild($domtree->createElement($k,$v));

                        if($k == "DescriptionLang"){//create nested elements
                            $level->setAttribute('value', 'en');
                            foreach($value as $k1=>$v1){
                                if(in_array($k1,array('Caption','Description','DetailsURL'))){
                                    $level->appendChild($domtree->createElement($k1,$v1));
                                }
                            }
                        }

                        if($k == 'PhotoURL'){//create photo elements
                            $images = $this->grab_pics($v);
                            if(!empty($images))
                            foreach($images as $i){
                               $url =  FULL_BASE_URL.'/property_images/'.$v.'/'.$i.'.jpg'; 
                              $currentElement->appendChild($domtree->createElement($k,$url));  
                            }
                        }
                    }
                }
            }
        }   
        echo $domtree->saveXML();
        exit;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM