在PHP中合并具有相同属性的XML文件


Merging XML files with same attribute in PHP

我花了两个晚上在这里寻找解决方案,但一直没能找到。我有多个XML文件,对于包含相同属性的节点,我想遍历所有这些文件,并将它们的所有节点合并到一个输出文件中。这里有一个例子:

File1.xml

<game rotnum="241">
  <gamedate> 123 </gamedate>
  <team1> Giants </team1>
  <team2> Eagles </team2>
</game>

File2.xml

<game rotnum="241">
  <line> 4 </line>
  <points> 200 </points>
</game>

合并的.xml

<game rotnum="241">
  <gamedate> 123 </gamedate>
  <team1> Giants </team1>
  <team2> Eagles </team2>
  <line> 4 </line>
  <points> 200 </points>
</game>

或多或少。我需要在PHP中完成这项工作,并且我认为使用DOM将比XSLT更容易(我对此了解不多)。

多个文件中有很多节点,我需要根据类似的rotnum属性来匹配数据。

我不知道我是否一定需要这样做,但这是我能想到的最简单的方法,可以将所有数据放入一个简单的XML对象中,我可以预先遍历该对象,并为每个游戏生成单独的表。

这些XML文件来自我通过SimpleXML创建的几个API提要,并将它们缓存在本地。。

function stripAndSaveFile($xml) {
    $game = $xml->game;
    $output = new SimpleXMLElement("<justbetlinesfeed></justbetlinesfeed>");
    for ($i = 0; $i < 16; $i++) {
        //Get the date of each game. 
        $spreadpoints = $game[$i]->line->spread->attributes()->points;
        $spreadteam1 = $game[$i]->line->spread->attributes()->team1adj;
        $spreadteam2 = $game[$i]->line->spread->attributes()->team2adj;
        $rotnum = $game[$i]->attributes()->team1rotnum;
        $insert = $output->addChild("game");
        $insert->addAttribute("rotnum", "$rotnum");
        $insert->addChild("spreadpoints", "$spreadpoints");
        $insert->addChild("spreadteam1", "$spreadteam1");
        $insert->addChild("spreadteam2", "$spreadteam2");
    }
    file_put_contents($this->filePath, $output->asXML());
}
}

在这种情况下,我更喜欢使用类似DomDocument 的东西

阅读文档:

$dom = new DomDocument();
$dom->load('filename.xml');
$games = $menu->getElementsByTagName("game");
foreach ($games as $game) {
    if($game->hasChildNodes)
    { 
         //Set element
         $element->nodeValue;
         //Store to array or similar
    }

这可能不是你想要的,但也许它会给你一个想法。这需要像Saxon这样的XSLT2.0处理器。

它所做的是遍历集合(用于测试的本地目录)中的所有XML文件,并通过根元素中的rotnum属性对它们进行分组。它有效地将根目录下的所有子目录合并到一个文件中。该文件在一个单独的目录中创建,名称基于rotnum值。

XSLT的输入可以是任何XML。我使用样式表本身作为输入。

这是一个例子。。。

"input_dir"目录中的XML文件:

file1.xml

<game rotnum="241">
  <gamedate> 123 </gamedate>
  <team1> Giants </team1>
  <team2> Eagles </team2>
</game>

file2.xml

<game rotnum="241">
  <line> 4 </line>
  <points> 200 </points>
</game>

XSLT2.0(使用Saxon HE 9.4测试)

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output indent="yes"/>
    <xsl:strip-space elements="*"/>
    <xsl:variable name="vCollection" select="collection('file:///C:/some_absolute_uri/input_dir?input=*.xml')"/>
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="/">
        <xsl:for-each-group select="$vCollection/*" group-by="@rotnum">
            <xsl:result-document href="file:///C:/some_absolute_uri/output_dir/{@rotnum}.xml">
                <xsl:copy>
                    <xsl:apply-templates select="@*"/>
                    <xsl:apply-templates select="$vCollection/*[@rotnum=current-grouping-key()]/*"/>                    
                </xsl:copy>
            </xsl:result-document>
        </xsl:for-each-group>
    </xsl:template>
</xsl:stylesheet>

"output_dir"目录中的XML文件:

241.xml

<game rotnum="241">
   <gamedate> 123 </gamedate>
   <team1> Giants </team1>
   <team2> Eagles </team2>
   <line> 4 </line>
   <points> 200 </points>
</game>