简体   繁体   English

PHP 重新格式化 XML 需要步骤

[英]PHP to reformat XML steps needed

I want to come up with the code myself but I need someone to please tell me what I'm dealing with here and layout the basic steps, not the actual code.我想自己编写代码,但我需要有人告诉我我在这里处理什么并布置基本步骤,而不是实际代码。 Right now my PHP does a file get contents via an http get web call.现在我的 PHP 通过 http get web 调用获取文件内容。 The data returned to me is XML node structure.返回给我的数据是XML节点结构。 Medical claims return, so there could be one claim or 200 claims returned, but all structured the same element wise, they just repeating.医疗索赔返回,因此可能有一个索赔或 200 个索赔返回,但所有的结构都是明智的,它们只是重复。 I need to take each element name that's within the CLAIM main element and have those names print horizontally across delineated by the dot I use in the 2nd example output.我需要获取 CLAIM 主元素中的每个元素名称,并让这些名称水平打印,由我在第二个示例 output 中使用的点划定。 I only need it to horizontally list these names once, not repeating.我只需要它水平列出这些名称一次,而不是重复。 Then I need to have the actual data that is in the middle of the elements also display horizontally with my dot delineation.然后我需要让元素中间的实际数据也用我的点划线水平显示。 So if there are 100 claims returned, I need that data to keep on displaying horizontally with my dot delineation.因此,如果返回了 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>


I did it, actually surprised myself.我做到了,其实我自己也很惊讶。 $file being the entire result I wanted to modify. $file 是我想要修改的整个结果。 This gives me the horizontal output I wanted.这给了我想要的水平 output。 The only problem now is getting a row count.现在唯一的问题是获得行数。 Any suggestions?有什么建议么? Something with some math involved, like take the column count I got and compare it to how many dot delineated positions there are on the total row output and divide by?涉及一些数学的东西,比如把我得到的列数与总行 output 上有多少个点划定的位置进行比较,然后除以?

To strip out column names, put the dot delineation in and return a count of how many columns要删除列名,请将点划线放入并返回多少列的计数

$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 ); 

My final code:我的最终代码:

    $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

 

I really appreciate that you took your time here Jack and wrote the code you did.我非常感谢您花时间在这里 Jack 并编写了您所做的代码。 I have a lot to learn by your code.我有很多东西要从你的代码中学习。 I would have never known that about RegEx.我永远不会知道 RegEx。 I never used "DOM" before.我以前从未使用过“DOM”。 My code is perhaps, well, it is, a hack job, and the math, that took me a while to test 30 different claims returns but it always gave me the correct row count.我的代码可能是,好吧,它是一个 hack 工作和数学,我花了一段时间来测试 30 个不同的索赔返回,但它总是给我正确的行数。 This is for a Cisco IVR so I need to have the XML stay as XML, but formatted like it does so the Cisco can maintain string delineation counts for its processing.这适用于 Cisco IVR,因此我需要将 XML 保持为 XML,但格式与它一样,以便 Cisco 可以为其处理维护字符串描述计数。 None of the will ever be on a terminal screen as its 100% machine to machine, hence the XML format all the way though.任何一个都不会出现在终端屏幕上,因为它的 100% 机器对机器,因此 XML 格式一直是。 Column counts and row counts are oh SO important in the IVR world.列数和行数在 IVR 世界中非常重要。

First things first: you are dealing with xml, and a complex one at that.首先要做的事情是:您正在处理 xml,而且是一个复杂的。 One thing that is not a good idea is to work on xml (or html, for that matter) with regex.一件事不是一个好主意是使用正则表达式处理 xml(或 html,就此而言)。 Search around and you'll see it's an almost universal consensus.搜索一下,你会发现这是一个几乎普遍的共识。

The most appropriate tools for working with xml are xpath and xquery.最适合使用 xml 的工具是 xpath 和 xquery。 Unfortunately, xpath support in php is terrible, so getting your expected output is going to involve a lot of mental gymnastics.不幸的是,php 中的 xpath 支持很糟糕,因此要获得您所期望的 output 将涉及很多心理操。

Having said that, since you asked to do it in php, here's an answer in php:话虽如此,既然您要求在 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: Output:

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

As I mentioned in the beginning, if your dataset is large enough and you have to do it frequently enough, it may be worth your while to learn about xpath/xquery and working with an xml database like BaseX.正如我在开头提到的那样,如果您的数据集足够大并且您必须经常这样做,那么学习 xpath/xquery 并使用 xml 数据库(如 BaseX)可能是值得的。

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

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