使用 Laravel 解析 XML 文件

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/49559092/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-14 17:34:44  来源:igfitidea点击:

Parsing XML file with Laravel

phplaravelxml-parsing

提问by roo

Ok, so I am pretty stuck on this. I have a semi-complex XML file which looks a bit like this:

好的,所以我很坚持这一点。我有一个半复杂的 XML 文件,它看起来有点像这样:

<?xml version="1.0" encoding="UTF-8"?>

<community ID="1234" POSTDATE="20180329" xmlns="" COMPANY="SAMPLE CO">
   <data1>
      <datatype ID="0001">
         <utpricing LT="1" STARTDATE="20150102" ENDDATE="20160102" BASEAMOUNT="99" CONCESSION="0.00" EFFAMOUNT="99" CONTYPE="SAMPLE" CONVALUE="0.00"/>
      <utpricing LT="1" STARTDATE="20150102" ENDDATE="20160102" BASEAMOUNT="99" CONCESSION="0.00" EFFAMOUNT="99" CONTYPE="SAMPLE" CONVALUE="0.00"/>
      <utpricing LT="1" STARTDATE="20150102" ENDDATE="20160102" BASEAMOUNT="99" CONCESSION="0.00" EFFAMOUNT="99" CONTYPE="SAMPLE" CONVALUE="0.00"/>
      <utpricing LT="1" STARTDATE="20150102" ENDDATE="20160102" BASEAMOUNT="99" CONCESSION="0.00" EFFAMOUNT="99" CONTYPE="SAMPLE" CONVALUE="0.00"/>
</data1>
          <datatype ID="0002">
             <utpricing LT="2" STARTDATE="20160102" ENDDATE="20170102" BASEAMOUNT="99" CONCESSION="0.00" EFFAMOUNT="99" CONTYPE="SAMPLE" CONVALUE="0.00"/>
          <utpricing LT="1" STARTDATE="20150102" ENDDATE="20160102" BASEAMOUNT="99" CONCESSION="0.00" EFFAMOUNT="99" CONTYPE="SAMPLE" CONVALUE="0.00"/>
          <utpricing LT="1" STARTDATE="20150102" ENDDATE="20160102" BASEAMOUNT="99" CONCESSION="0.00" EFFAMOUNT="99" CONTYPE="SAMPLE" CONVALUE="0.00"/>
          <utpricing LT="1" STARTDATE="20150102" ENDDATE="20160102" BASEAMOUNT="99" CONCESSION="0.00" EFFAMOUNT="99" CONTYPE="SAMPLE" CONVALUE="0.00"/>
    </datatype>
</data1>
  <data2>
      <data2 ID="141" NAME="IAM | 1 | 1.00" SQFTMIN="111" SQFTMAX="222"/>
      <data2 ID="142" NAME="ASA | 1 | 1.00" SQFTMIN="111" SQFTMAX="222"/>
      <data2 ID="143" NAME="MPL | 1 | 1.00" SQFTMIN="111" SQFTMAX="222"/>
      <data2 ID="144" NAME="EBI | 1 | 1.00" SQFTMIN="111" SQFTMAX="222"/>
      <data2 ID="145" NAME="TOF | 2 | 2.00" SQFTMIN="111" SQFTMAX="222"/>
   </data2>

   <samples>
      <sample ID="001" AVAILDATE="20152901" STATUS="Unavailable" data1TYPE="001" UNITCAT="1X1" SOMEVALUE="50.00" data2ID="141">
         <item1 ID="59" item2="50.00" DESCRIPTION="Sample Description"/>
         <offeredterm LT="2" BASEAMOUNT="1120.00" TOTALCONCESSION="0.00" EFFECTIVESAMPLE="1120.00" CONTYPE="T" CONVALUE="0.00"/>
      </sample>
    <sample ID="002" AVAILDATE="20152901" STATUS="Unavailable" data1TYPE="001" UNITCAT="1X1" SOMEVALUE="50.00" data2ID="141">
         <item1 ID="59" item2="50.00" DESCRIPTION="Sample Description"/>
         <offeredterm LT="2" BASEAMOUNT="1120.00" TOTALCONCESSION="0.00" EFFECTIVESAMPLE="1120.00" CONTYPE="T" CONVALUE="0.00"/>
      </sample>

So I have tried to parse this a few ways, but what I want to end up with is a structured collection that I can then run operations on like selecting all items from data1which have the same data1TYPEas the datatype IDetc.

所以我尝试通过几种方式解析它,但我最终想要的是一个结构化的集合,然后我可以运行操作,比如从中选择与等等data1相同的所有项目。data1TYPEdatatype ID

Currently my code looks like this:

目前我的代码是这样的:

$XML = Storage::disk('local')->get('data\XML.xml');
$random = collect(json_decode(json_encode((array) simplexml_load_string($XML)), true));

I have been able to retrieve an object like this and then loop through by the indexes and build a separate collection for each xml tag. This doesn't feel that efficient though and I'm not sure how I would best run the comparison operations later on.

我已经能够检索这样的对象,然后通过索引循环并为每个 xml 标记构建一个单独的集合。但这感觉效率不高,我不确定以后如何最好地运行比较操作。

Any ideas?

有任何想法吗?

回答by TytonDon

Welcome to the world of xml! The way you are doing it is the best way that I am currently aware of. A basic example of xml to json is the way you are doing it:

欢迎来到 xml 的世界!你这样做的方式是我目前所知道的最好的方式。xml 到 json 的一个基本示例是您执行此操作的方式:

$xml = simplexml_load_string($xml_string);

$json = json_encode($xml);

$array = json_decode($json,TRUE);

I do see that you are type-hinting array before your simplexml_load_string call. Is there a reason for that?

我确实看到您在 simplexml_load_string 调用之前是类型提示数组。有什么原因吗?

Also when you state that you are not sure how to run the comparison, what exactly do you mean by that? Is your xml static, meaning never changing, or does it change in size and/or scope?

此外,当您说您不确定如何进行比较时,您到底是什么意思?你的 xml 是静态的,意味着永远不会改变,还是它的大小和/或范围发生了变化?

回答by Mark

I created a package that works very well with Laravel to help you convert XML into an array.

我创建了一个与 Laravel 配合得很好的包,以帮助您将 XML 转换为数组。

https://github.com/mtownsend5512/xml-to-array

https://github.com/mtownsend5512/xml-to-array

Install it, and you can make use of the global helper function for Laravel xml_to_array.

安装它,你就可以使用 Laravel 的全局辅助函数了xml_to_array

Because your XML is malformed, I tried my best to fix it so I could provide an example:

由于您的 XML 格式错误,我已尽力修复它,以便提供一个示例:

    $xml = <<<XML
<?xml version="1.0" encoding="UTF-8"?>
<community ID="1234" POSTDATE="20180329"
    xmlns="" COMPANY="SAMPLE CO">
    <data1>
        <datatype ID="0001">
            <utpricing LT="1" STARTDATE="20150102" ENDDATE="20160102" BASEAMOUNT="99" CONCESSION="0.00" EFFAMOUNT="99" CONTYPE="SAMPLE" CONVALUE="0.00"/>
            <utpricing LT="1" STARTDATE="20150102" ENDDATE="20160102" BASEAMOUNT="99" CONCESSION="0.00" EFFAMOUNT="99" CONTYPE="SAMPLE" CONVALUE="0.00"/>
            <utpricing LT="1" STARTDATE="20150102" ENDDATE="20160102" BASEAMOUNT="99" CONCESSION="0.00" EFFAMOUNT="99" CONTYPE="SAMPLE" CONVALUE="0.00"/>
            <utpricing LT="1" STARTDATE="20150102" ENDDATE="20160102" BASEAMOUNT="99" CONCESSION="0.00" EFFAMOUNT="99" CONTYPE="SAMPLE" CONVALUE="0.00"/>
        </datatype>
        <datatype ID="0002">
            <utpricing LT="2" STARTDATE="20160102" ENDDATE="20170102" BASEAMOUNT="99" CONCESSION="0.00" EFFAMOUNT="99" CONTYPE="SAMPLE" CONVALUE="0.00"/>
            <utpricing LT="1" STARTDATE="20150102" ENDDATE="20160102" BASEAMOUNT="99" CONCESSION="0.00" EFFAMOUNT="99" CONTYPE="SAMPLE" CONVALUE="0.00"/>
            <utpricing LT="1" STARTDATE="20150102" ENDDATE="20160102" BASEAMOUNT="99" CONCESSION="0.00" EFFAMOUNT="99" CONTYPE="SAMPLE" CONVALUE="0.00"/>
            <utpricing LT="1" STARTDATE="20150102" ENDDATE="20160102" BASEAMOUNT="99" CONCESSION="0.00" EFFAMOUNT="99" CONTYPE="SAMPLE" CONVALUE="0.00"/>
        </datatype>
    </data1>
    <data2>
        <data2 ID="141" NAME="IAM | 1 | 1.00" SQFTMIN="111" SQFTMAX="222"/>
        <data2 ID="142" NAME="ASA | 1 | 1.00" SQFTMIN="111" SQFTMAX="222"/>
        <data2 ID="143" NAME="MPL | 1 | 1.00" SQFTMIN="111" SQFTMAX="222"/>
        <data2 ID="144" NAME="EBI | 1 | 1.00" SQFTMIN="111" SQFTMAX="222"/>
        <data2 ID="145" NAME="TOF | 2 | 2.00" SQFTMIN="111" SQFTMAX="222"/>
    </data2>
    <samples>
        <sample ID="001" AVAILDATE="20152901" STATUS="Unavailable" data1TYPE="001" UNITCAT="1X1" SOMEVALUE="50.00" data2ID="141">
            <item1 ID="59" item2="50.00" DESCRIPTION="Sample Description"/>
            <offeredterm LT="2" BASEAMOUNT="1120.00" TOTALCONCESSION="0.00" EFFECTIVESAMPLE="1120.00" CONTYPE="T" CONVALUE="0.00"/>
        </sample>
        <sample ID="002" AVAILDATE="20152901" STATUS="Unavailable" data1TYPE="001" UNITCAT="1X1" SOMEVALUE="50.00" data2ID="141">
            <item1 ID="59" item2="50.00" DESCRIPTION="Sample Description"/>
            <offeredterm LT="2" BASEAMOUNT="1120.00" TOTALCONCESSION="0.00" EFFECTIVESAMPLE="1120.00" CONTYPE="T" CONVALUE="0.00"/>
        </sample>
    </samples>
</community>
XML;

dd(xml_to_array($xml));

Now your XML will be a valid array which can be manipulated. Because of your extensive use of attributes you will have a lot of data clean up to do. I recommend wrapping it in a Laravel Collection by doing collect($xml), then checking Laravel's Collection documentationto figure out the best way to transform the data in the way you want it.

现在您的 XML 将是一个可以操作的有效数组。由于您广泛使用属性,您将需要清理大量数据。我建议通过执行 将其包装在 Laravel 集合中collect($xml),然后查看Laravel 的集合文档以找出以您想要的方式转换数据的最佳方法。