我在stackoverflow中有点新意,所以请事先原谅我。 :)
我正在尝试将对象与同一BranchCode合并,基本上只是将Branch作为主Product节点的子节点。请参阅下面的示例XML。感谢。
我有这个XML(simpleXMLElement->asXML()
):
<?xml version="1.0" encoding="utf-8"?>
<ArrayOfProduct xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Product>
<Customer>238500</Customer>
<ProductCode>AAA-02-2166</ProductCode>
<BranchCode>14</BranchCode>
<Available>0.00</Available>
<AvailableCSL>0.00</AvailableCSL>
<AvailableGlobally>0.00</AvailableGlobally>
</Product>
<Product>
<Customer>238500</Customer>
<ProductCode>AAA-02-2166</ProductCode>
<BranchCode>150</BranchCode>
<Available>0.00</Available>
<AvailableCSL>0.00</AvailableCSL>
<AvailableGlobally>0.00</AvailableGlobally>
</Product>
<Product>
<Customer>238500</Customer>
<ProductCode>AAA-02-2166</ProductCode>
<BranchCode>226</BranchCode>
<Available>0.00</Available>
<AvailableCSL>0.00</AvailableCSL>
<AvailableGlobally>0.00</AvailableGlobally>
</Product>
<Product>
<Customer>238500</Customer>
<ProductCode>AAA-02-2166</ProductCode>
<BranchCode>227</BranchCode>
<Available>0.00</Available>
<AvailableCSL>0.00</AvailableCSL>
<AvailableGlobally>0.00</AvailableGlobally>
</Product>
<Product>
<Customer>238500</Customer>
<ProductCode>AAA-02-2166</ProductCode>
<BranchCode>26</BranchCode>
<Available>0.00</Available>
<AvailableCSL>0.00</AvailableCSL>
<AvailableGlobally>0.00</AvailableGlobally>
</Product>
<Product>
<Customer>238500</Customer>
<ProductCode>AAA-02-2166</ProductCode>
<BranchCode>34</BranchCode>
<Available>0.00</Available>
<AvailableCSL>0.00</AvailableCSL>
<AvailableGlobally>0.00</AvailableGlobally>
</Product>
<Product>
<Customer>238500</Customer>
<ProductCode>AAA-02-2166</ProductCode>
<BranchCode>35</BranchCode>
<Available>0.00</Available>
<AvailableCSL>0.00</AvailableCSL>
<AvailableGlobally>0.00</AvailableGlobally>
</Product>
<Product>
<Customer>238500</Customer>
<ProductCode>AAA-02-2166</ProductCode>
<BranchCode>400A</BranchCode>
<Available>0.00</Available>
<AvailableCSL>0.00</AvailableCSL>
<AvailableGlobally>0.00</AvailableGlobally>
</Product>
<Product>
<Customer>238500</Customer>
<ProductCode>AAA-02-2166</ProductCode>
<BranchCode>405A</BranchCode>
<Available>0.00</Available>
<AvailableCSL>0.00</AvailableCSL>
<AvailableGlobally>0.00</AvailableGlobally>
</Product>
<Product>
<Customer>238500</Customer>
<ProductCode>AAA-02-2166</ProductCode>
<BranchCode>460A</BranchCode>
<Available>0.00</Available>
<AvailableCSL>0.00</AvailableCSL>
<AvailableGlobally>0.00</AvailableGlobally>
</Product>
<Product>
<Customer>238500</Customer>
<ProductCode>AAA-02-2166</ProductCode>
<BranchCode>57</BranchCode>
<Available>0.00</Available>
<AvailableCSL>0.00</AvailableCSL>
<AvailableGlobally>0.00</AvailableGlobally>
</Product>
<Product>
<Customer>238500</Customer>
<ProductCode>AAA-02-2166</ProductCode>
<BranchCode>83</BranchCode>
<Available>0.00</Available>
<AvailableCSL>0.00</AvailableCSL>
<AvailableGlobally>0.00</AvailableGlobally>
</Product>
<Product>
<Customer>238500</Customer>
<ProductCode>AAA-02-2166</ProductCode>
<BranchCode>C3</BranchCode>
<Available>0.00</Available>
<AvailableCSL>0.00</AvailableCSL>
<AvailableGlobally>0.00</AvailableGlobally>
</Product>
<Product>
<Customer>238500</Customer>
<ProductCode>AAA-02-2166</ProductCode>
<BranchCode>Global</BranchCode>
<Available>0.00</Available>
<AvailableCSL>0.00</AvailableCSL>
<AvailableGlobally>0.00</AvailableGlobally>
</Product>
<Product>
<Customer>238500</Customer>
<ProductCode>AAA-051-2030</ProductCode>
<BranchCode>14</BranchCode>
<Available>0.00</Available>
<AvailableCSL>0.00</AvailableCSL>
<AvailableGlobally>0.00</AvailableGlobally>
</Product>
<Product>
<Customer>238500</Customer>
<ProductCode>AAA-051-2030</ProductCode>
<BranchCode>150</BranchCode>
<Available>0.00</Available>
<AvailableCSL>0.00</AvailableCSL>
<AvailableGlobally>0.00</AvailableGlobally>
</Product>
<Product>
<Customer>238500</Customer>
<ProductCode>AAA-051-2030</ProductCode>
<BranchCode>226</BranchCode>
<Available>0.00</Available>
<AvailableCSL>0.00</AvailableCSL>
<AvailableGlobally>0.00</AvailableGlobally>
</Product>
<Product>
<Customer>238500</Customer>
<ProductCode>AAA-051-2030</ProductCode>
<BranchCode>227</BranchCode>
<Available>0.00</Available>
<AvailableCSL>0.00</AvailableCSL>
<AvailableGlobally>0.00</AvailableGlobally>
</Product>
<Product>
<Customer>238500</Customer>
<ProductCode>AAA-051-2030</ProductCode>
<BranchCode>26</BranchCode>
<Available>0.00</Available>
<AvailableCSL>0.00</AvailableCSL>
<AvailableGlobally>0.00</AvailableGlobally>
</Product>
<Product>
<Customer>238500</Customer>
<ProductCode>AAA-051-2030</ProductCode>
<BranchCode>34</BranchCode>
<Available>0.00</Available>
<AvailableCSL>0.00</AvailableCSL>
<AvailableGlobally>0.00</AvailableGlobally>
</Product>
<Product>
<Customer>238500</Customer>
<ProductCode>AAA-051-2030</ProductCode>
<BranchCode>35</BranchCode>
<Available>0.00</Available>
<AvailableCSL>0.00</AvailableCSL>
<AvailableGlobally>0.00</AvailableGlobally>
</Product>
<Product>
<Customer>238500</Customer>
<ProductCode>AAA-051-2030</ProductCode>
<BranchCode>400A</BranchCode>
<Available>0.00</Available>
<AvailableCSL>0.00</AvailableCSL>
<AvailableGlobally>0.00</AvailableGlobally>
</Product>
<Product>
<Customer>238500</Customer>
<ProductCode>AAA-051-2030</ProductCode>
<BranchCode>405A</BranchCode>
<Available>0.00</Available>
<AvailableCSL>0.00</AvailableCSL>
<AvailableGlobally>0.00</AvailableGlobally>
</Product>
<Product>
<Customer>238500</Customer>
<ProductCode>AAA-051-2030</ProductCode>
<BranchCode>460A</BranchCode>
<Available>5.00</Available>
<AvailableCSL>0.00</AvailableCSL>
<AvailableGlobally>0.00</AvailableGlobally>
</Product>
<Product>
<Customer>238500</Customer>
<ProductCode>AAA-051-2030</ProductCode>
<BranchCode>57</BranchCode>
<Available>0.00</Available>
<AvailableCSL>0.00</AvailableCSL>
<AvailableGlobally>0.00</AvailableGlobally>
</Product>
<Product>
<Customer>238500</Customer>
<ProductCode>AAA-051-2030</ProductCode>
<BranchCode>83</BranchCode>
<Available>0.00</Available>
<AvailableCSL>0.00</AvailableCSL>
<AvailableGlobally>0.00</AvailableGlobally>
</Product>
<Product>
<Customer>238500</Customer>
<ProductCode>AAA-051-2030</ProductCode>
<BranchCode>C3</BranchCode>
<Available>0.00</Available>
<AvailableCSL>0.00</AvailableCSL>
<AvailableGlobally>0.00</AvailableGlobally>
</Product>
<Product>
<Customer>238500</Customer>
<ProductCode>AAA-051-2030</ProductCode>
<BranchCode>Global</BranchCode>
<Available>0.00</Available>
<AvailableCSL>0.00</AvailableCSL>
<AvailableGlobally>5.00</AvailableGlobally>
</Product>
</ArrayOfProduct>
我想要一个与此类似的输出:
<?xml version="1.0" encoding="utf-8"?>
<ArrayOfProduct xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Product>
<Customer>238500</Customer>
<ProductCode>AAA-50-3535</ProductCode>
<Branch>
<BranchCode>C3</BranchCode>
<Available>10.00</Available>
<AvailableCSL>0.00</AvailableCSL>
<AvailableGlobally>100.00</AvailableGlobally>
</Branch>
<Branch>
<BranchCode>A5</BranchCode>
<Available>20.00</Available>
<AvailableCSL>0.00</AvailableCSL>
<AvailableGlobally>100.00</AvailableGlobally>
</Branch>
....
....
</Product>
....
....
</ArrayOfProduct>
答案 0 :(得分:0)
没有任何可以合并文档的内置函数,因此您必须“手动”执行此操作。一种方法是在PHP中使用DOM。选择要通过XPath处理的<Product>
个节点,创建一个移动所有子节点的<Branch>
节点,然后将<Branch>
个节点附加到正确的<Product>
。
$dom = new DOMDocument;
// Those two options are purely for cosmetic reasons, you can remove them
$dom->formatOutput = true;
$dom->preserveWhiteSpace = false;
$dom->load('old.xml');
$ProductNodes = array();
$DOMXPath = new DOMXPath($dom);
foreach ($DOMXPath->query('/ArrayOfProduct/Product') as $Product)
{
// Create a new <Branch/>
$Branch = $dom->createElement('Branch');
// Move the nodes to the <Branch/>, except for <Customer/> and <ProductCode/>
$childNodes = $DOMXPath->query('./*[name() != "Customer"][name() != "ProductCode"]', $Product);
foreach ($childNodes as $child)
{
$Branch->appendChild($Product->removeChild($child));
}
$key = $Product->getElementsByTagName('Customer')->item(0)->textContent
. ':'
. $Product->getElementsByTagName('ProductCode')->item(0)->textContent;
// If it's not the first product with that combination of Customer:ProductCode, we remove the
// node, otherwise we keep it and we'll append other branches to it
if (isset($ProductNodes[$key]))
{
$Product->parentNode->removeChild($Product);
}
else
{
$ProductNodes[$key] = $Product;
}
$ProductNodes[$key]->appendChild($Branch);
}
echo $dom->saveXML();
答案 1 :(得分:0)
或者,您可以使用Identity Transform更改文档的结构。这是一个这样的例子:(这个不处理PI和评论节点)
<强> copy.xsl 强>
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" encoding="utf-8" indent="yes" />
<xsl:template match="@* | *">
<xsl:copy>
<xsl:apply-templates select="@* | *"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/ArrayOfProduct/Product">
<!-- Check if it's the first Product node with that combination of Customer and ProductCode -->
<xsl:if test="not(preceding-sibling::Product[Customer = current()/Customer and ProductCode = current()/ProductCode])">
<xsl:copy>
<!-- Copy the Customer and ProductCode nodes first -->
<xsl:copy-of select="Customer | ProductCode" />
<!-- Create a Branch for every Product with that combination of Customer and ProductCode -->
<xsl:for-each select="/ArrayOfProduct/Product[Customer = current()/Customer and ProductCode = current()/ProductCode]">
<Branch>
<!-- Copy their children, except for Customer and ProductCode -->
<xsl:copy-of select="*[name() != 'Customer'][name() != 'ProductCode']"/>
</Branch>
</xsl:for-each>
</xsl:copy>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
您可以在PHP中运行它:
$xml = new DOMDocument;
$xml->load('old.xml');
$xsl = new DOMDocument;
$xsl->load('copy.xsl');
$xslt = new XSLTProcessor;
$xslt->importStylesheet($xsl);
echo $xslt->transformToXml($xml);