使用XSL从URL合并2 XML

时间:2014-06-04 03:09:58

标签: php xml xslt

我正在使用一个API,它提供了两个用于从中提取内容的网址。

第一个给我一个产品清单,但每个产品的信息有限。

第二个网址,使用?productId = 1我可以提取有关特定产品的其余数据。

我想要做的是将这两件事合并为一件,这样我以后就可以轻松导入wordpress或其他地方了。

我尝试过使用DOM + PHP,但是我无法让它工作,也许xsl会是更好的解决方案吗?

File1.svc

<products>
  <product>
    <product_id> 1 </product_id>
    <product_name> Product 1 </product_name>
  </product>
  <product>
    <product_id> 2 </product_id>
    <product_name> Product 2 </product_name>
  </product>
</products>

File2.svc?的productId = 1

<results>
  <product product_id="1">
    <price_from> 100 </price_from>
    <price_to> 300 </price_to>
  </product>
</results>

我要导出的结果:

<products>
  <product>
    <product_id> 1 </product_id>
    <product_name> Product 1 </product_name>
    <price_from> 100 </price_from>
    <price_to> 300 </price_to>
  </product>
  <product>
    <product_id> 2 </product_id>
    <product_name> Product 2 </product_name>
    <price_from> 400 </price_from>
    <price_to> 500 </price_to>
  </product>
</products>

3 个答案:

答案 0 :(得分:1)

它应该运作良好:

#File1.svc
$xml_A = <<<XML
<products>
    <product>
        <product_id> 1 </product_id>
        <product_name> Product 1 </product_name>
    </product>  
</products>
XML;

#File2.svc?productId=1
$xml_B = <<<XML
<results>
    <product product_id="1">
        <price_from> 100 </price_from>
        <price_to> 300 </price_to>
    </product>
</results>
XML;

$a = new SimpleXMLElement($xml_A); //or new SimpleXMLElement($URL, null, true);
$b = new SimpleXMLElement($xml_B); //or new SimpleXMLElement($URL, null, true);

$priceFromElement = $b->product[0]->price_from;
$priceToElement   = $b->product[0]->price_to;

$a->product[0]->addChild($priceFromElement->getName(), $priceFromElement);
$a->product[0]->addChild($priceToElement->getName(), $priceToElement);

echo $a->asXML(); //merged

答案 1 :(得分:1)

或者,您可以解析它们,在数组上构建它们,然后创建另一个。考虑这个例子:

// if you want rough and gun processing
$data = array();
// sample values
@$raw_xml1 = simplexml_load_string('<products> <product> <product_id> 1 </product_id> <product_name> Product 1 </product_name> </product> <product> <product_id> 2 </product_id> <product_name> Product 2 </product_name> </product></products>');
@$raw_xml2 = simplexml_load_string('<results> <product product_id="1"> <price_from> 100 </price_from> <price_to> 300 </price_to> </product> <product product_id="2"> <price_from>400</price_from> <price_to>500</price_to> </product></results>');

// the extraction
foreach($raw_xml1->product as $key => $value) {
    $product_id = trim((string) $value->product_id);
    $data[$product_id] = array(
        'product_id' => $product_id,
        'product_name' => trim((string) $value->product_name),
    );
}

foreach($raw_xml2->product as $key => $value) {
    $product_id = trim((string) $value->attributes()['product_id']);
    $data[$product_id]['price_from'] = trim((string) $value->price_from);
    $data[$product_id]['price_to'] = trim((string) $value->price_to);
}

$final_xml = '<?xml version="1.0" encoding="UTF-8"?>';
$final_xml .= '<products>';
foreach($data as $key => $value) {
    $final_xml .= '<product>';
    foreach($value as $index => $element) {
        $final_xml .= "<$index>$element</$index>";
    }
    $final_xml .= '</product>';
}
$final_xml .= '</products>';

// save it
$xml = new SimpleXMLElement($final_xml);
$xml->asXML('text.xml');
// saved as xml file, should be saved on the same level as this php

答案 2 :(得分:1)

这是一个XSLT解决方案,它根据文件名附带的ID选择文件:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output indent="yes"/>

    <xsl:template match="products">
        <copy>
            <xsl:apply-templates/>
        </copy>
    </xsl:template>

    <xsl:template match="product">
        <xsl:copy>
            <xsl:copy-of select="product_id"/>
            <xsl:copy-of select="product_name"/>
            <xsl:variable name="filepath" select="concat('File2.svc?productId=',normalize-space(product_id))"/>
            <xsl:copy-of select="document($filepath)/results/product/*"/>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

可以检查ID 属性是否正确,但我认为检查?productId=已经足够了,因为它会按照您的ID过滤结果说。