如果我的XML文件中包含以下数据;
<?xml version="1.0" encoding="UTF-8"?>
<Document xmlns="urn:iso:std:iso:20022:tech:xsd:pain.008.001.02" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<CstmrDrctDbtInitn>
<PmtInf>
<PmtInfId>5n7gfUaPGK</PmtInfId>
<PmtMtd>DD</PmtMtd>
<NbOfTxs>1</NbOfTxs>
<CtrlSum>200.2</CtrlSum>
<PmtTpInf>
<SvcLvl>
<Cd>SEPA</Cd>
</SvcLvl>
<LclInstrm>
<Cd>CORE</Cd>
</LclInstrm>
<SeqTp>RCUR</SeqTp>
</PmtTpInf>
<DrctDbtTxInf>
<PmtId>
<EndToEndId>nmu5AOhE7G</EndToEndId>
</PmtId>
</DrctDbtTxInf>
</PmtInf>
<PmtInf>
<PmtInfId>5jAcoNoId3</PmtInfId>
<PmtMtd>DD</PmtMtd>
<NbOfTxs>3</NbOfTxs>
<CtrlSum>100.5</CtrlSum>
<PmtTpInf>
<SvcLvl>
<Cd>SEPA</Cd>
</SvcLvl>
<LclInstrm>
<Cd>CORE</Cd>
</LclInstrm>
<SeqTp>FRST</SeqTp>
</PmtTpInf>
<DrctDbtTxInf>
<PmtId>
<EndToEndId>nmu5AbdfG</EndToEndId>
</PmtId>
</DrctDbtTxInf>
<DrctDbtTxInf>
<PmtId>
<EndToEndId>nmu5A3r5jgG</EndToEndId>
</PmtId>
</DrctDbtTxInf>
</PmtInf>
</CstmrDrctDbtInitn>
</Document>
我如何访问第二个<NbOfTxs>
块(值为3)中的<PmtInf>
而不是<NbOfTxs>
块中的<PmtInf>
(其中值为1) )?
如果我只使用以下代码行;
$FRSTTransaction = $xml->getElementsByTagName('NbOfTxs')->nodeValue;
我不知道我试图访问哪个<NbOfTxs>
。
每个付款清单之间的唯一区别是<SeqTp>
。总共将有4个支付块。
我正在尝试计算每个付款清单中<DrctDbtTxInf>
个版块的数量,然后将此值放入<NbOfTxs>
。
<PmtId>
<EndToEndId>nmu5AOhE7G</EndToEndId>
</PmtId>
</DrctDbtTxInf>
我尝试的代码如下;
$filename = date('Y-W').'.xml'; //2014-26.xml
$xml = new DOMDocument;
$xml->load($filename);
$NumberTransactions = 0;
$RCURTransaction = $xml->getElementsByTagName('DrctDbtTxInf');
$NodeValue = $xml->getElementsByTagName('NbOfTxs')->nodeValue;
foreach ($RCURTransaction as $Transaction) {
$NodeValue = $NodeValue + 1;
}
$Document = simplexml_load_file($filename);
$Document->CstmrDrctDbtInitn->PmtInf->NbOfTxs = $NodeValue;
$Document->asXML($filename);
我没有收到任何错误,它似乎无法访问节点值。
答案 0 :(得分:1)
Read the manual。 DOMDocument::getElementsByTagName
不返回节点,它返回DOMNodeList
类的实例。这个类实现了Traversable
接口(这意味着你可以foreach
),并且拥有自己的item
一个方法(再次参见{{3} }})。
您正在尝试访问认为是nodeValue
实例的DOMNode
属性,但实际上是DOMNodeList
实例。如您所见the manual,没有nodeValue
属性可用。而是从此列表中获取特定节点,然后获取节点值:
$nodes = $xml->getElementsByTagName('NbOfTxs');
foreach ($nodes as $node)
echo $node->nodeValue, PHP_EOL;//first, second, third node
或者,如果您愿意,例如,只能看到此节点第三次出现的值:
if ($nodes->length > 2)//zero-indexed!
echo $nodes->item(2)->nodeValue, PHP_EOL;
else
echo 'Error, only ', $nodes->length, ' occurrences of that node found', PHP_EOL;
通常,底线确实是RTM。 DOMDocument::getElementsByTagName
的文档清楚地显示了给定方法的返回类型。如果它是特定类的实例,则可以在PHP网站上单击该返回类型,并将您链接到该类的手册页。导航API并不比那更简单,恕我直言:
//from the docs
public DOMNodeList DOMDocument::getElementsByTagName ( string $name )
// class::methodName arguments + expected type
|-> return type, links to docs for this class
更新
解决你在更新的问题中提到的事情:
我假设每个PmtInf
都是付款广告,但我认为所有SeqTp
标记都是PmtTpInf
标记的子标记。由于我们正在使用DOMNodeList
,其中包含DOMNode
个实例。 in the manual是第一件事。正如您所看到的,每个DOMNode
都有许多方便的属性和方法:$childNodes
,$nodeName
和$parentNode
是我们将在此处使用的内容。
$payments = $xml->getElementsByTagName('PmtTpInf');//don't get PmtInf, we can access that through `PmtTpInf` nodes' parentNode property
$idx = -1;
$counts = array();
$parents = array();
foreach ($payments as $payment)
{
if (!$parents || $parents[$idx] !== $payment->parentNode)
{//current $payment is not a child of last processed payment block
$parents[++$idx] = $payment->parentNode;//add reference to new payment block
$count[$idx] = 0;//set count to 0
}
foreach ($payment->childNodes as $child)
{
if ($child->nodeName === 'SeqTp')
++$counts[$idx];//add 1 to count
}
}
好的,现在我们有2个数组$parents
,其中包含每个付款块,$counts
,其中包含该付款清单中所有SeqTp
个模块的总数。让我们着手添加/更新这些数据:
foreach ($parents as $idx => $block)
{//iterate over the payment blocks
$nbNode = null;//no node found yet
for ($i=0;$i<$block->childNodes->length;++$i)
{
if ($block->childNodes->item($i)->nodeName === 'NbOfTxs')
{
$nbNode = $block->childNodes->item($i);
break;//found the node, stop here
}
}
if ($nbNode === null)
{//NbOfTxs tag does not exist yet
$nbNode = $xml->createElement('NbOfTxs', 0);//create new node
$block->appendChild($nbNode);//add as child of the payment-block node
}
$nbNode->nodeValue = $counts[$idx];//set value using the counts array we constructed above
}
最后,要保存此更新的XML dom:
$xml->save($filename);
全部,根本不需要simplexml_load_file
,因为它解析了DOMDocument
已为您做过的XML DOM。