2013-10-27 65 views
0

我试图通过PHP脚本来转换XML文件。我有以下结构:用PHP编辑XML结构

<?xml version="1.0"?> 
<persons> 

<person id="1"> 
     <periods>3</periods> 
     <name id="John"/> 
     <times> 
     <time> 
      <day id="1"/> 
      <time>35:28</time > 
      <length>8000</length> 
     </time> 
     <time> 
      <day id="4"/> 
      <time>8:28</time > 
      <length>2000</length> 
     </time> 
     <time> 
      <day id="5"/> 
      <time>3:03</time > 
      <length>1000</length> 
     </time> 
     </times> 
    </person> 

<person id="2"> 
     <periods>3</periods> 
     <name id="James"/> 
     <times> 
     <time> 
      <day id="3"/> 
      <time>45:20</time > 
      <length>15000</length> 
     </time> 
     <time> 
      <day id="5"/> 
      <time>4:48</time > 
      <length>1500</length> 
     </time> 
     </times> 
    </person> 
etc… 
etc… 
</persons> 

每个人都有一个或多个时间元素。我想转换结构,因此每个人元素只有一个时间元素(如下面的结构)。

<?xml version="1.0"?> 
<persons> 
    <person id="1"> 
     <periods>3</periods> 
     <name id="John"/> 
     <times> 
     <time> 
      <day id="1"/> 
      <time>35:28</time > 
      <length>8000</length> 
     </time> 
     </times> 
    </person> 

    <person id="1"> 
     <periods>3</periods> 
     <name id="John"/> 
     <times> 
     <time> 
      <day id="4"/> 
      <time>8:28</time > 
      <length>2000</length> 
     </time> 
     </times> 
    </person> 

    <person id="1"> 
     <periods>3</periods> 
     <name id="John"/> 
     <times> 
     <time> 
      <day id="5"/> 
      <time>3:03</time > 
      <length>1000</length> 
     </time> 
     </times> 
    </person> 

<person id="2"> 
     <periods>2</periods> 
     <name id="James"/> 
     <times> 
     <time> 
      <day id="3"/> 
      <time>45:20</time > 
      <length>15000</length> 
     </time> 
     </times> 
    </person> 

<person id="2"> 
     <periods>2</periods> 
     <name id="James"/> 
     <times> 
     <time> 
      <day id="5"/> 
      <time>4:48</time > 
      <length>1500</length> 
     </time> 
     </times> 
    </person> 
</persons> 

有没有办法做到这一点?

+0

那么,就克隆要复制的节点,改变你从中删除的时间节点(我用'DOMDocument'&有点xpath'本的',但你可以创建和XSLT为了这)。但是:您的原始结构似乎比您想要的输出更可行。是否有一个特殊的原因需要输出? – Wrikken

+0

@Wrikken是的,有一个原因。我需要将其转换为JSON。它使JSON代码更加可行(对我而言)。 – Jorik

回答

0

我所知道的英语很糟糕,但我会尽力回答:)

我认为,这个任务的实施,将适合的SimpleXML和DOM扩展。 以下是执行所需转换的简单脚本。 input.xml是包含源文本的文件。 该算法的结果将被保存到output.xml文件。

<?php 
$simpleXml = new SimpleXMLElement(file_get_contents('input.xml')); 
$personElements = $simpleXml->person; 

$personForAppend = array(); 
$personsForRemove = array(); 

foreach ($personElements as $personElement) { 
    $timeElements = $personElement->times->xpath("child::time"); 
    $numberOfTimeElements = count($timeElements); 

    if ($numberOfTimeElements > 1) { 
     $personDomElement = dom_import_simplexml($personElement); 
     $backupTimeDomElementArray = array(); 

     foreach ($timeElements as $timeElement) { 
      $timeDomElement = dom_import_simplexml($timeElement); 
      $backupTimeDomElementArray[] = clone $timeDomElement; 
      $timeDomElement->parentNode->removeChild(
       $timeDomElement 
      ); 
     } 

     while ($timeDomElement = array_shift($backupTimeDomElementArray)) { 
      $copyPersonDomElement = clone $personDomElement; 
      $copyPersonDomElement->getElementsByTagName('times') 
       ->item(0)->appendChild($timeDomElement); 
      $personForAppend[] = $copyPersonDomElement; 
     } 
     $personsForRemove[] = $personDomElement; 
    } 
} 

foreach ($personForAppend as $personDomeNode) { 
    $personDomElement->parentNode->appendChild($personDomeNode); 
} 

foreach ($personsForRemove as $personDomElement) { 
    $personDomElement->parentNode->removeChild($personDomElement); 
} 
$simpleXml->saveXML('output.xml'); 
+0

谢谢你的回答。 output.xml文件只显示一个人的第一个时间元素。我希望每个人都能得到一个时间元素,就像第二个例子中的结构一样(参见上文)。 – Jorik

+0

我为我的粗心大意道歉。我稍微改变了算法。我希望那是你需要的。 – Anchoret

+0

完美的作品!非常感谢你! – Jorik