【问题标题】:Split XML files with PHP not outputting top level parent node使用 PHP 拆分 XML 文件不输出顶级父节点
【发布时间】:2017-10-28 06:57:28
【问题描述】:

我正在尝试将 XML 文件分成两个文件,longrentals.xml 和 shortrentals.xml,但遇到了我遇到的最后一个障碍。以下是我希望发生的事情:

  • rentals.xml 被解析,并且对于 term = "short" 的每个实例,该条目的顶部父 "property" 节点被保存到 shortrentals.xml。
  • 从rentals.xml 文件中删除每个实例(提取后)。
  • shortrentals.xml 文件已保存。
  • 原始文件中的其余条目保存到 longrentals.xml。

XML结构如下:

<property>
...
  <rent>
    <term>short</term>
    <freq>week</freq>
    <price_peak>5845</price_peak>
    <price_high>5845</price_high>
    <price_medium>4270</price_medium>
    <price_low>3150</price_low>
  </rent>
...
</property>

我使用的代码如下:

$destination = new DOMDocument;
$destination->preserveWhiteSpace = true;
$destination->loadXML('<?xml version="1.0" encoding="utf-8"?><root></root>');

$source = new DOMDocument;
$source->load('file/rentals.xml');

$xp = new DOMXPath($source);
$destRoot = $destination->getElementsByTagName("root")->item(0);

foreach ($xp->query('/root/property/rent[term = "short"]') as $item) {
    $newItem = $destination->importNode($item, true);
    $destRoot->appendChild($newItem);
    $item->parentNode->removeChild($item);
}

$source->save("file/longrentals.xml");
$destination->formatOutput = true;
$destination->save("file/shortrentals.xml");

除了 shortrentals.xml 中的输出仅包含出租节点而不包含顶级父属性节点之外,此方法有效。此外,从 longrentals.xml 中删除的条目仅删除了 Rent 子节点。那么,请问如何使用我的代码升级?

【问题讨论】:

    标签: php xml domdocument


    【解决方案1】:

    您可以使用 DOMNode 的 parentNode 属性在结构中上一级(类似于您在 removeChild 代码中的操作方式)...

    foreach ($xp->query('/root/property/rent[term = "short"]') as $item) {
        $property = $item->parentNode;
        $newItem = $destination->importNode($property, true);
        $destRoot->appendChild($newItem);
        $property->parentNode->removeChild($property);
    }
    

    【讨论】:

    • 噢!绝对是“看不到(XML)树木的木材情况”。非常感谢奈杰尔:)。
    【解决方案2】:

    或者,考虑使用专用 XML 转换语言 XSLT 来创建这两个没有 foreach 循环的 XML 文件。在这里,XSLT 作为字符串嵌入,但可以像任何其他 XML 文件一样从文件中解析。假定的 XML 结构:&lt;root&gt;&lt;property&gt;&lt;rent&gt;...

    shortrentals.xml 输出

    // Load XML and XSL sources
    $xml = new DOMDocument;
    $xml->load('file/rentals.xml');
    
    $xslstr = '<?xml version="1.0" ?> 
               <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">  
                <xsl:output method="xml" indent="yes"/>
                <xsl:strip-space elements="*"/>
    
                 <xsl:template match="/root">
                     <xsl:copy>
                        <xsl:apply-templates select="property[rent/term=\'short\']"/>
                    </xsl:copy>
                 </xsl:template> 
    
                 <xsl:template match="property">
                     <xsl:copy>
                        <xsl:copy-of select="*"/>
                    </xsl:copy>
                 </xsl:template>
    
                </xsl:stylesheet>';
    
    $xsl = new DOMDocument;
    $xsl->loadXML($xslstr);
    
    // Configure transformer
    $proc = new XSLTProcessor;
    $proc->importStyleSheet($xsl);
    
    // Transform XML source
    $newXML = new DOMDocument;
    $newXML = $proc->transformToXML($xml);
    
    // Output file
    file_put_contents('file/shortrentals.xml', $newXML);
    

    longrentals.xml (使用Identity Transform 和空模板删除节点)

    // Load XML and XSL sources
    $xml = new DOMDocument;
    $xml->load('file/rentals.xml');
    
    $xslstr = '<?xml version="1.0" ?> 
               <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">  
                <xsl:output method="xml" indent="yes"/>
                <xsl:strip-space elements="*"/>
    
                 <!-- Identity Transform -->
                 <xsl:template match="@*|node()">
                     <xsl:copy>
                        <xsl:apply-templates select="@*|node()"/>
                    </xsl:copy>
                 </xsl:template> 
    
                 <!-- Remove Non-Short Terms --> 
                <xsl:template match="property[rent/term=\'short\']"/>
    
                </xsl:stylesheet>';
    
    $xsl = new DOMDocument;
    $xsl->loadXML($xslstr);
    
    // Configure transformer
    $proc = new XSLTProcessor;
    $proc->importStyleSheet($xsl);
    
    // Transform XML source
    $newXML = new DOMDocument;
    $newXML = $proc->transformToXML($xml);
    
    // Output file
    file_put_contents('file/longrentals.xml', $newXML);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-01-10
      • 2021-01-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多