代码之家  ›  专栏  ›  技术社区  ›  Philipp M

php-如果元素每个记录有相似的标记,则获取正确的xml值

  •  1
  • Philipp M  · 技术社区  · 6 年前

    php-如果元素每个记录有相似的标记,则获取正确的xml值

    我正在获取以下XML文件:

    XML文件:

    <?xml version='1.0' encoding='UTF-8'?>
    <abc:ABCData xmlns:abc="http://www.abc-example.com" xmlns:xyz="http:/www.xyz-example.com">
    <abc:ABCRecords>
     <abc:ABCRecord>
     <abc:ABC>5EXZX4LPK</abc:ABC>
      <abc:Entity>
        <abc:Name>I Bornheim</abc:Name>
        <abc:Periods>
          <abc:Period>
            <abc:Start>2017-01-01</abc:Start>
            <abc:End>2017-12-31</abc:End>
            <abc:Type>ACCOUNTING</abc:Type>
          </abc:Period>
          <abc:Period>
            <abc:Start>2007-09-01</abc:Start>
            <abc:Type>RELATIONSHIP</abc:Type>
          </abc:Period>
        </abc:Periods>      
      </abc:Entity>
    </abc:ABCRecord>
    <abc:ABCRecord>
      <abc:ABC>5967007LI</abc:ABC>
      <abc:Entity>
        <abc:Name>SUN BANK</abc:Name>
        <abc:Periods>
          <abc:Period>
            <abc:Start>2018-01-01</abc:Start>
            <abc:End>2018-12-31</abc:End>
            <abc:Type>BALANCED</abc:Type>
          </abc:Period>
          <abc:Period>
            <abc:Start>2008-09-01</abc:Start>
            <abc:Type>PARENT</abc:Type>
          </abc:Period>
        </abc:Periods>          
      </abc:Entity>
    </abc:ABCRecord>
    </abc:ABCRecords>
    </abc:ABCData>
    

    …使用此脚本,我将值输出为csv:

    PHP文件:

    <?php
    
    $reader = new XMLReader();
    $reader->open('php://stdin');
    
    $output = fopen('php://stdout', 'w');
    fputcsv($output, ['id', 'name']);
    
    $xmlns = [
      'abc' => 'http://www.abc-example.com'
    ];
    
    $dom   = new DOMDocument;
    $xpath = new DOMXpath($dom);
    foreach ($xmlns as $prefix => $namespaceURI) {
      $xpath->registerNamespace($prefix, $namespaceURI);
    }
    
    while (
      $reader->read() && 
      (
        $reader->localName !== 'ABCRecord' || 
        $reader->namespaceURI !== $xmlns['abc']
      )
    ) {
      continue;
    }
    
    while ($reader->localName === 'ABCRecord') {
      if ($reader->namespaceURI === 'http://www.abc-example.com') {
        $node = $reader->expand($dom);
        fputcsv(
          $output, 
          [
            $xpath->evaluate('string(abc:ABC)', $node),
            $xpath->evaluate('string(abc:Entity/abc:Name)', $node)
          ]
        );
      }
    
      $reader->next('ABCRecord');
    } 
    

    …这样地:

    输出:

    5EXZX4LPK,"I Bornheim"
    5967007LI,"SUN BANK"
    

    然而…如果每个期间记录具有相同的标记定义,如何获取正确的“期间”值?

    期望输出:

    5EXZX4LPK,"I Bornheim",2017-01-01,2017-12-31,"ACCOUNTING",2007-09-01,"RELATIONSHIP"
    5967007LI,"SUN BANK",2018-01-01,2018-12-31,"BALANCED",2008-09-01,"PARENT"
    
    2 回复  |  直到 6 年前
        1
  •  1
  •   ThW    6 年前

    您可以使用该类型对期间分组并获取第一个分组结果:

    $xpath->evaluate(
        'string(
            abc:Entity/abc:Periods/abc:Period[
                abc:Type = "ACCOUNTING" or abc:Type="BALANCED"
            ][1]/abc:Type
        )', 
        $node
    ),
    

    或者你检查一下这里是否有 abc:End 子元素:

    $xpath->evaluate(
        'string(
            abc:Entity/abc:Periods/abc:Period[
                count(abc:End) = 0
            ][1]/abc:Type
        )', 
        $node
    ),
    
        2
  •  1
  •   miken32 Amit D    6 年前

    您可以简单地使用xpath的索引符号;想想 <abc:Period> 数组中的元素。记住,xpath索引是基于一的,而不是基于零的。

    ...
        fputcsv(
          $output, 
          [
            $xpath->evaluate('string(abc:ABC)', $node),
            $xpath->evaluate('string(abc:Entity/abc:Name)', $node),
            $xpath->evaluate('string(abc:Entity/abc:Periods/abc:Period[1]/abc:Start)', $node),
            $xpath->evaluate('string(abc:Entity/abc:Periods/abc:Period[1]/abc:End)', $node),
            $xpath->evaluate('string(abc:Entity/abc:Periods/abc:Period[1]/abc:Type)', $node),
            $xpath->evaluate('string(abc:Entity/abc:Periods/abc:Period[2]/abc:Start)', $node),
            $xpath->evaluate('string(abc:Entity/abc:Periods/abc:Period[2]/abc:Type)', $node),
          ]
        );
    ...
    

    输出:

    id,name
    5EXZX4LPK,"I Bornheim",2017-01-01,2017-12-31,ACCOUNTING,2007-09-01,RELATIONSHIP
    5967007LI,"SUN BANK",2018-01-01,2018-12-31,BALANCED,2008-09-01,PARENT
    
    推荐文章