Php 访问文件中其他区域也使用的特定节点

Php 访问文件中其他区域也使用的特定节点,php,xml,Php,Xml,如果我的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>

如果我的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>
它不知道我正在尝试访问哪个

每个付款区块之间的唯一区别是
。总共将有4个付款区块

我试图计算每个付款区块中的
区块数,然后将该值输入

我没有收到任何错误,只是似乎无法访问节点值。

DOMDocument::getElementsByTagName
不返回节点,它返回
DOMNodeList
类的实例。这个类实现了
可遍历的
接口(这意味着您可以
foreach
它),并且有一个自己的
(同样,请参见)

您正试图访问您认为是
DOMNode
实例的
nodeValue
属性,但实际上是
DOMNodeList
实例。如您所见,没有可用的
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再简单不过了,IMHO:

//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
实例组成。这是第一件要做的事。如您所见,每个
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
    }
}
好的,现在我们有两个数组,
$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
}

仅此而已,根本不需要
simplexml\u load\u file
,因为它解析XML DOM,而
DOMDocument
已经为您做了

您是如何解析XML的(
DOMDocument
,我怀疑)?你犯了什么错误?请准确描述问题,并告诉我们您迄今为止试图解决的问题I编辑了我的帖子如果您想看一看,我对XML非常陌生,很抱歉我没有说清楚..我注意到您的编辑,您实际上在这个问题上添加了另一个问题(如何计算子节点+更新XML文件)。我把这个问题的答案加在我的答案上。附言:不时地接受一个答案会给人们更多的动力去回答你的问题。如果答案有帮助,请投票,这样人们会觉得写答案所花费的时间和精力是值得赞赏的更新我的答案:添加了如何更新、创建添加、查找节点和保存更新的XML文件的示例代码,一举我始终接受并投票如果答案有帮助,我真的很感谢您为帮助我所花费的时间和精力。我现在就试试你的答案,然后马上给你回复结果。谢谢
//from the docs
public DOMNodeList DOMDocument::getElementsByTagName ( string $name )
       //          class::methodName                  arguments + expected type
       |-> return type, links to docs for this class
$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
    }
}
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->save($filename);