这是我们现在拥有的XML:
<persons>
<person>
<firstname>John</firstname>
<surname>Doe</surname>
<age></age>
</person>
<person>
<firstname>Jane</firstname>
<surname>Doe</surname>
<age></age>
<sex>Female</sex>
</person>
</persons>
正如您所看到的,第一组元素只有三个标记,即名字,姓氏和年龄,而第二组有另外的标记名称性别。
我们需要的是让XML中的所有元素组都包含每个组具有的所有标记,在这种情况下,第一组也应该包含性别标记,但是处于空白状态,如下所示:
<persons>
<person>
<firstname>John</firstname>
<surname>Doe</surname>
<age></age>
<sex></sex>
</person>
<person>
<firstname>Jane</firstname>
<surname>Doe</surname>
<age></age>
<sex>Female</sex>
</person>
</persons>
此外,如果有第三,第四或第50组有另一个名为昵称的新标签?在这种情况下,所有组都应该具有标记昵称,但处于空白状态。
我怎样才能在PHP中有效地做到这一点?
答案 0 :(得分:2)
使用SimpleXML,脚本会传递两个:一个用于查找所有可能的标记,另一个用于创建空元素:
$str = <<<STR
<persons>
<person>
<firstname>John</firstname>
<surname>Doe</surname>
<age></age>
</person>
<person>
<firstname>Jane</firstname>
<surname>Doe</surname>
<age></age>
<sex>Female</sex>
</person>
</persons>
STR;
$xml = simplexml_load_string($str);
// Create an array of all the possible tags
$tags = array();
foreach($xml->person as $person)
{
$current_tags = array_keys(get_object_vars($person));
$tags = array_unique(array_merge($tags, $current_tags));
}
// Add empty tags to elements who don't have them
foreach($xml->person as $person)
{
foreach($tags as $tag)
{
if(!property_exists($person, $tag))
{
$person->$tag = '';
}
}
}
// Output the new XML
echo $xml->asXML();
答案 1 :(得分:2)
最容易使其长期维护(例如,预期更多新字段和类似内容)将使用包含所有必需字段的XSLT处理XML:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/persons">
<persons>
<xsl:apply-templates select="person"/>
</persons>
</xsl:template>
<xsl:template match="person">
<person>
<firstname><xsl:value-of select="firstname"/></firstname>
<surname><xsl:value-of select="surname"/></surname>
<age><xsl:value-of select="age"/></age>
<sex><xsl:value-of select="sex"/></sex>
</person>
</xsl:template>
</xsl:stylesheet>
然后,每当您从生成器服务获得新副本时,请执行(manual)
$dom = new DOMDocument;
$dom->load('people.xml');
$xsl = new DOMDocument;
$xsl->load('people.xsl');
$proc = new XSLTProcessor;
$proc->importStyleSheet($xsl);
echo $proc->transformToXML($dom);
这将产生(demo)
<?xml version="1.0"?>
<persons>
<person>
<firstname>John</firstname>
<surname>Doe</surname>
<age/>
<sex/>
</person>
<person>
<firstname>Jane</firstname>
<surname>Doe</surname>
<age/>
<sex>Female</sex>
</person>
</persons>
答案 2 :(得分:2)
我同意@Gordon这里最好的解决方案是XSLT。但是,我建议使用稍微不同的XSL:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="person">
<person>
<xsl:apply-templates select="@* | *[not(self::sex)]"/>
<sex><xsl:value-of select="sex"/></sex>
</person>
</xsl:template>
</xsl:stylesheet>
I tried it out与W3Schools的在线XSLT评估员合作,并按要求运行。