繁体   English   中英

PHP 重新格式化 XML 需要步骤

[英]PHP to reformat XML steps needed

我想自己编写代码,但我需要有人告诉我我在这里处理什么并布置基本步骤,而不是实际代码。 现在我的 PHP 通过 http get web 调用获取文件内容。 返回给我的数据是XML节点结构。 医疗索赔返回,因此可能有一个索赔或 200 个索赔返回,但所有的结构都是明智的,它们只是重复。 我需要获取 CLAIM 主元素中的每个元素名称,并让这些名称水平打印,由我在第二个示例 output 中使用的点划定。 我只需要它水平列出这些名称一次,而不是重复。 然后我需要让元素中间的实际数据也用我的点划线水平显示。 因此,如果返回了 100 个索赔,我需要这些数据继续以我的点划线水平显示。

<CLAIM_LIST>
  <CLAIM>
    <fund_code>TTG-PMA N351</fund_code>
    <fund_name>TTG</fund_name>
    <ProviderTIN>444555666</ProviderTIN>
</CLAIM>
<CLAIM>
    <fund_code>XXX-PMA N444</fund_code>
    <fund_name>ILWU</fund_name>
    <ProviderTIN>888777666</ProviderTIN>
</CLAIM>
<CLAIM>
</CLAIM_LIST>

TURN the above into the below. I know how to do the dot delineation, and the column_names and data name elements. 


<column_names>
    fund_code·fund_name·ProviderTIN
 </column_names>

<data>
 TTG-PMA N351·TTG·44555666·XXX-PMA N444·ILWU·888777666
 </data>


我做到了,其实我自己也很惊讶。 $file 是我想要修改的整个结果。 这给了我想要的水平 output。 现在唯一的问题是获得行数。 有什么建议么? 涉及一些数学的东西,比如把我得到的列数与总行 output 上有多少个点划定的位置进行比较,然后除以?

要删除列名,请将点划线放入并返回多少列的计数

$xml = simplexml_load_string($file);

  foreach($xml->children()->children() as $child){
     $claimsNames .= $child->getName() . "·" . "";  
    $col_count++;
    
}

Then to strip out the data in all the elements and also put dot delineation in

 $claimsData = trim(preg_replace('/<[^>]*>/', '   ', $file));  
  $claimsData = str_replace( '      ', '·', $claimsData ); 

我的最终代码:

    $file = file_get_contents($remote_url, false, $context);   // Open the 
    file using the HTTP headers set above   
   
       $start_time  = microtime(true);
       $col_count = 0;
       $row_count = 0;   
   
       $xml = simplexml_load_string($file);
   
     // THE LOOP! To strip column names out of XML elements and display how 
    many columns
   
      foreach($xml->children()->children() as $child)
    {
         $claimsNames .= $child->getName() . "·" . "";
    
        $col_count++;
    
    
    }

      $claimsData = trim(preg_replace('/<[^>]*>/', '   ', $file));  
      $claimsData = str_replace( '      ', '·', $claimsData ); 

      $row_count1 = count(explode('·', $claimsData));   // how many total dots 
    starting at 1
       $ColPlusOne = ($col_count + 1);              //28 plus 1 = 29
      $row_count2 = ($row_count1 / $ColPlusOne);         //  divide above by 
    number of columns and round, to give total number of rows  
      $row_count3 = ceil($row_count2*1)/1;             // round return up 
  
  
       if ($col_count == "28") {       //checking for no record
    
         $col_count = $col_count;
         $row_count3 = $row_count3;
       
    } else {
    
         $col_count = "0";
          $row_count3 = "0";
    }
  
   
       $time = round( (microtime(true) - $start_time), 4);      

    
    ?>

    <response>
    <time><?=$time?></time>
    <cols><?=$col_count?></cols>
    <rows><?=$row_count3?></rows>
    <column_names>
    <?=$claimsNames?>    
    </column_names>
    <data>
    <?=$claimsData?>                                                       
    </data>
    </response>

It gives output like this:
<response>
<time>0.0029</time>
<cols>28</cols>
<rows>83</rows>
<column_names>
fund_code·fund_name·ProviderTIN·provider_name·claim_num·status·dos·dos_end·ProcessDate·patient_id·patient_dob·patient_name·patient_lastname·patient_firstname·patient_middlename·patient_relationship·Payee·AmountBilled·AmountCovered·AmountPaid·AmountCopay·Discount·Deductible·PatientAmount·dup·Source·ClaimSource·OriginalClaimNumber·
</column_names>
<data>
TTG-PMA N351·TTG·111222999··20200312-209·Issued·20200303·20200303·20200312·0000037725·19510915·VAN HALEN EDDIE·VAN HALEN·EDDIE··Participant·Provider·8127.00·2888.80·2888.80·0.00·5238.20·0.00·0.00··AMBICAB·SG·20200312-209··TTG-PMA N351·TTG·111222999··20200318-1361·Issued·20200303·20200303·20200318·0000037725·19510915·VAN HALEN EDDIE·VAN HALEN·EDDIE··Participant·Provider·26.00·9.99·9.99·0.00·16.01·0.00·0.00··AMBICAB·SG·20200318-1361··TTG-PMA N351·TTG·111222999··20200318-1362·Issued·20200303·20200303·20200318·0000037725·19510915·VAN HALEN EDDIE·VAN HALEN·EDDIE··Participant·Provider·17.00·10.31·10.31·0.00·6.69·0.00·0.00··AMBICAB·SG·20200318-1362··TTG-PMA N351·TTG·252363454··20200407-1405·Issued·20200303·20200303·20200407·0000037725·19510915·VAN HALEN EDDIE·VAN HALEN·EDDIE··Participant·Provider·765.00·180.57·180.57·0.00·584.43·0.00·0.00··AMBICAB·SG·20200407-1405··TTG-PMA N351·TTG·472728752··20191119-3554·Issued·20191021·20191021·20191120·0000037725·19510915·VAN HALEN

 

我非常感谢您花时间在这里 Jack 并编写了您所做的代码。 我有很多东西要从你的代码中学习。 我永远不会知道 RegEx。 我以前从未使用过“DOM”。 我的代码可能是,好吧,它是一个 hack 工作和数学,我花了一段时间来测试 30 个不同的索赔返回,但它总是给我正确的行数。 这适用于 Cisco IVR,因此我需要将 XML 保持为 XML,但格式与它一样,以便 Cisco 可以为其处理维护字符串描述计数。 任何一个都不会出现在终端屏幕上,因为它的 100% 机器对机器,因此 XML 格式一直是。 列数和行数在 IVR 世界中非常重要。

首先要做的事情是:您正在处理 xml,而且是一个复杂的。 一件事不是一个好主意是使用正则表达式处理 xml(或 html,就此而言)。 搜索一下,你会发现这是一个几乎普遍的共识。

最适合使用 xml 的工具是 xpath 和 xquery。 不幸的是,php 中的 xpath 支持很糟糕,因此要获得您所期望的 output 将涉及很多心理操。

话虽如此,既然您要求在 php 中执行此操作,因此 php 中的答案如下:

$string = <<<XML
[your xml snippet above]
XML;

//loading boilerplate
$claimsdoc = new DOMDocument();
$claimsdoc->loadXML($string);
$claimsdoc_xpath = new DOMXPath($claimsdoc);

$claims = $claimsdoc_xpath->evaluate('count(//CLAIM)'); //get the number of CLAIMs
$tags = $claimsdoc_xpath->evaluate('count(//CLAIM[1]//*)');//get the number of tags per CLAIM 

//get the column names and create the xml output
$cols = $claimsdoc_xpath->evaluate(".//CLAIM[1]//*");
$colnames = htmlspecialchars("<column_names>", ENT_QUOTES) . "\n<br>";    
for ($x = 0; $x < $tags; $x++) { 
  $result = $cols[$x];
  $colnames .= "$result->tagName";
  if ($x < $tags-1)
        $colnames.=" * ";  
 }    
$colnames .= "\n<br>" . htmlspecialchars("</column_names>", ENT_QUOTES);

//get the claim data and create the xml output
$data = htmlspecialchars("<data>", ENT_QUOTES) . "\n<br>";
for ($x = 1; $x <= $claims; $x++) { 
  $result = $claimsdoc_xpath->evaluate("concat(.//CLAIM[$x]//fund_code/text(),' * ',.//CLAIM[$x]//fund_name,' * ',.//CLAIM[$x]//ProviderTIN)");
  $data .=$result;
  if ($x < $claims)
        $data .=" * ";  
} 
$data .= "\n<br>" . htmlspecialchars("</data>", ENT_QUOTES);

echo $colnames;
echo "\n<br>";
echo $data;

Output:

<column_names>
fund_code * fund_name * ProviderTIN
</column_names>
<data>
TTG-PMA N351 * TTG * 444555666 * XXX-PMA N444 * ILWU * 888777666
</data>

正如我在开头提到的那样,如果您的数据集足够大并且您必须经常这样做,那么学习 xpath/xquery 并使用 xml 数据库(如 BaseX)可能是值得的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM