XML覆盖以前的节点

时间:2018-01-25 05:27:29

标签: php xml

我的工作有大量的xml配置文件,一个在节点中调用的标记。

示例:

<root>
  <pages>
    <page>
      <file_input_folder>\\Trucks\_MANUAL</file_input_folder> 
      <file_input_virtual_dir>MANUAL</file_input_virtual_dir> 
      <file_output_folder>C:\MANUAL</file_output_folder>
      <fields>
       <field>InvoiceNumber</field>
       <field>CustomerNumber</field>
      </fields>
    </page>
    <page>
      <file_input_folder>\\Trucks\_MANUAL</file_input_folder> 
      <file_input_virtual_dir>MANUAL</file_input_virtual_dir> 
      <file_output_folder>C:\Auto</file_output_folder>
      <fields>
       <field>InvoiceNumber</field>
       <field>AutoNumber</field>
      </fields>
    </page>
  </pages>
</root>

我想要的是如下所示,第二页节点中的重复元素将自动从第一页节点加载:

<root>
  <pages>
    <page>
      <file_input_folder>\\Trucks\_MANUAL</file_input_folder> 
      <file_input_virtual_dir>MANUAL</file_input_virtual_dir> 
      <file_output_folder>C:\MANUAL</file_output_folder>
      <fields>
       <field>InvoiceNumber</field>
       <field>CustomerNumber</field>
      </fields>
    </page>
    <page>
      <file_output_folder>C:\Auto</file_output_folder>
      <fields>
       <field>AutoNumber</field>
      </fields>
    </page>
  </pages>
</root>

我的xml文件非常大,如果上面的话可以完成近2k linem,它可以缩小到几百行。

我的环境是php,但欢迎任何语言,例如python和.net。

提前致谢

1 个答案:

答案 0 :(得分:0)

第二个例子不起作用,因为很难知道哪些元素被替换(你希望<field>AutoNumber</field>替换<field>CustomerNumber</field>但是只留下<field>InvoiceNumber</field> - 怎么办?)< / p>

这对你的事情来说可能有点过头了,但无论如何都写得很有意思。

我解决它的方法是为任何页面元素使用一个模板,它包含真正常见的数据,然后每个页面都有它拥有的模板额外的数据。

我在每个页面中使用'id'属性来标识您想要哪个页面的值以及用于标识模板的'id'属性。该页面使用(如有必要)“模板”属性来说明它使用的模板。这意味着您可以根据需要使用多个模板。

<?php
error_reporting(E_ALL);
ini_set('display_errors', 1);

function mergeElement ( $source, &$dest )   {
    foreach ( $source as $node ) {
        $nodeName = $node->getName();
        // If it's a nested item, go down to next level
        if ( isset( $dest->$nodeName ) && count($node->children()) > 0)    {
            mergeElement($node, $dest->$nodeName);
        }
        else    {
            $dest->addChild( $nodeName, (string)$node);
        }
    }
}

function fetchPage ( $pageName, $source )    {
    $pageData = $source->xpath ( "//pages/page[@id='{$pageName}']");
    // If no page found, exit
    if ( count($pageData) == 0 )    {
        return false;
    }
    $pageData = $pageData[0];
    unset($pageData['id']);
    // If no template - return data as is
    if ( !isset($pageData['template'])) {
        return $pageData;
    }
    $template = $source->xpath ( "//template[@id='{$pageData['template']}']")[0];
    // Add in page to template
    mergeElement ( $template, $pageData );
    // remove template id from XML
    unset($pageData['template']);

    return $pageData;
}

$xml = simplexml_load_file("data.xml");

// Fetch the data for 'pageB'
$page = fetchPage ( "pageB", $xml );
echo $page->asXML();

data.xml包含......

<?xml version="1.0" encoding="UTF-8"?>
<root>
    <template id="1">
        <file_input_folder>\\Trucks\_MANUAL</file_input_folder>
        <file_input_virtual_dir>MANUAL</file_input_virtual_dir>
        <fields>
            <field>InvoiceNumber</field>
        </fields>
    </template>
    <pages>
        <page id="pageA" template="1">
            <file_output_folder>C:\MANUAL</file_output_folder>
            <fields>
                <field>CustomerNumber</field>
            </fields>
        </page>
        <page id="pageB" template="1">
            <file_output_folder>C:\Auto</file_output_folder>
            <fields>
                <field>AutoNumber</field>
            </fields>
        </page>
        <page id="pageC">
            <file_output_folder>C:\Auto1</file_output_folder>
            <fields>
                <field>AutoNumber1</field>
            </fields>
        </page>
    </pages>
</root>

上面显示了模板以及它如何链接到数据页面,最后一页不使用模板并按原样返回。

产生'pageB'的输出(虽然这是格式化的)......

<page>
    <file_output_folder>C:\Auto</file_output_folder>
    <fields>
        <field>AutoNumber</field>
        <field>InvoiceNumber</field>
    </fields>
    <file_input_folder>\\Trucks\_MANUAL</file_input_folder>
    <file_input_virtual_dir>MANUAL</file_input_virtual_dir>
</page>