【问题标题】:Convert XML with name spaces to json in php/Laravel在 php/Laravel 中将带有名称空间的 XML 转换为 json
【发布时间】:2019-02-04 23:29:29
【问题描述】:

我花了两天时间尝试将 XML 转换为 json,但没有成功。

我已经尝试过通常的simplexml_load_stringXMLReaderSimpleXMLElement

当 SearchResults 只有一项时,我可以使用 `XMLReader 读取数据。但是当返回多个项目时,我不知道该怎么办。

```

<?xml version="1.0" encoding="utf-8"?>
<DataSet xmlns="http://exampleurl.com/">
  <xs:schema id="NewDataSet" xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
    <xs:element name="NewDataSet" msdata:IsDataSet="true" msdata:UseCurrentLocale="true">
      <xs:complexType>
        <xs:choice minOccurs="0" maxOccurs="unbounded">
          <xs:element name="SearchResults">
            <xs:complexType>
              <xs:sequence>
                <xs:element name="VehicleID" type="xs:long" minOccurs="0" />
                <xs:element name="make" type="xs:string" minOccurs="0" />
                <xs:element name="model" type="xs:string" minOccurs="0" />
                <xs:element name="series" type="xs:string" minOccurs="0" />
                <xs:element name="engine" type="xs:string" minOccurs="0" />
                <xs:element name="yearrange" type="xs:string" minOccurs="0" />
                <xs:element name="details" type="xs:string" minOccurs="0" />
                <xs:element name="chassis" type="xs:string" minOccurs="0" />
                <xs:element name="Countryoforigin" type="xs:string" minOccurs="0" />
                <xs:element name="VIN" type="xs:string" minOccurs="0" />
              </xs:sequence>
            </xs:complexType>
          </xs:element>
          <xs:element name="ChargeDetails">
            <xs:complexType>
              <xs:sequence>
                <xs:element name="ChargeApplies" type="xs:long" minOccurs="0" />
              </xs:sequence>
            </xs:complexType>
          </xs:element>
          <xs:element name="vehicleRawDetails">
            <xs:complexType>
              <xs:sequence>
                <xs:element name="licenceplate" type="xs:string" minOccurs="0" />
                <xs:element name="VIN" type="xs:string" minOccurs="0" />
                <xs:element name="make" type="xs:string" minOccurs="0" />
                <xs:element name="model" type="xs:string" minOccurs="0" />
                <xs:element name="submodel" type="xs:string" minOccurs="0" />
                <xs:element name="year" type="xs:string" minOccurs="0" />
                <xs:element name="bodystyle" type="xs:string" minOccurs="0" />
                <xs:element name="vehicletype" type="xs:string" minOccurs="0" />
                <xs:element name="chassisnumber" type="xs:string" minOccurs="0" />
                <xs:element name="enginenumber" type="xs:string" minOccurs="0" />
                <xs:element name="cc" type="xs:string" minOccurs="0" />
                <xs:element name="countryoforigin" type="xs:string" minOccurs="0" />
                <xs:element name="fueltype" type="xs:string" minOccurs="0" />
                <xs:element name="transmission" type="xs:string" minOccurs="0" />
                <xs:element name="speeds" type="xs:string" minOccurs="0" />
                <xs:element name="modelcode" type="xs:string" minOccurs="0" />
              </xs:sequence>
            </xs:complexType>
          </xs:element>
        </xs:choice>
      </xs:complexType>
    </xs:element>
  </xs:schema>
  <diffgr:diffgram xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" xmlns:diffgr="urn:schemas-microsoft-com:xml-diffgram-v1">
    <NewDataSet xmlns="">
      <SearchResults diffgr:id="SearchResults1" msdata:rowOrder="0">
        <VehicleID>13971</VehicleID>
        <make>SUBARU</make>
        <model>LEGACY</model>
        <series>BE</series>
        <engine>1994cc, EJ204 F4 16v DOHC MPFI {114KW}</engine>
        <yearrange>12/98~04/03</yearrange>
        <details>  B4 RS, 4D Sedan, AWD, AT/MT</details>
        <chassis>BE5</chassis>
        <Countryoforigin>JAPAN</Countryoforigin>
        <VIN>BE5</VIN>
      </SearchResults>
      <SearchResults diffgr:id="SearchResults2" msdata:rowOrder="1">
        <VehicleID>14379</VehicleID>
        <make>SUBARU</make>
        <model>LEGACY</model>
        <series>BE</series>
        <engine>1994cc, EJ208 F4 16v DOHC Twin Turbo MPFI {206KW}</engine>
        <yearrange>12/98~04/03</yearrange>
        <details>  B4 RSK, 4D Sedan, AWD, MT</details>
        <chassis>BE5</chassis>
        <Countryoforigin>JAPAN</Countryoforigin>
        <VIN>BE5</VIN>
      </SearchResults>
      <ChargeDetails diffgr:id="ChargeDetails1" msdata:rowOrder="0">
        <ChargeApplies>1</ChargeApplies>
      </ChargeDetails>
    </NewDataSet>
  </diffgr:diffgram>
</DataSet>

```

我可以验证 XML 是否正确,因为我尝试了在线转换器并且结果可用。而我得到空数组或空对象。

有人可以帮忙吗?

【问题讨论】:

标签: php json xml laravel


【解决方案1】:

所以我发现的 XML 到 JSON 函数确实工作得很好,但它不能满足我的需要,因为它将名称空间合并到键名中,我需要从键中删除名称空间。

问题是当您在 XML 元素中合并命名空间时,转换为数组或 JSON 时,命名空间的子节点会被删除。我意识到如果在将字符串转换为 XML 元素之前从 XML 字符串中删除命名空间,那么 json_encode 函数会按预期工作并且不会删除任何数据。

因此,对于遇到此问题的其他人,这是我根据需要解决问题的方法。

我知道发送给我的 XML 没有命名冲突。使用命名空间的唯一原因是识别 XML 数据部分的来源。 我知道所有正在使用的命名空间 我所做的就是在这里获得这些信息

function removeNamespaceFromXML( $xml )
{
// Because I know all of the the namespaces that will possibly appear in 
// in the XML string I can just hard code them and check for 
// them to remove them
$toRemove = ['rap', 'turss', 'crim', 'cred', 'j', 'rap-code', 'evic'];
// This is part of a regex I will use to remove the namespace declaration from string
$nameSpaceDefRegEx = '(\S+)=["\']?((?:.(?!["\']?\s+(?:\S+)=|[>"\']))+.)["\']?';

// Cycle through each namespace and remove it from the XML string


foreach( $toRemove as $remove ) {
        // First remove the namespace from the opening of the tag
        $xml = str_replace('<' . $remove . ':', '<', $xml);
        // Now remove the namespace from the closing of the tag
        $xml = str_replace('</' . $remove . ':', '</', $xml);
        // This XML uses the name space with CommentText, so remove that too
        $xml = str_replace($remove . ':commentText', 'commentText', $xml);
        // Complete the pattern for RegEx to remove this namespace declaration
        $pattern = "/xmlns:{$remove}{$nameSpaceDefRegEx}/";
        // Remove the actual namespace declaration using the Pattern
        $xml = preg_replace($pattern, '', $xml, 1);
    }

// Return sanitized and cleaned up XML with no namespaces
return $xml;
}

function namespacedXMLToArray($xml)
{
    // One function to both clean the XML string and return an array
    return json_decode(json_encode(simplexml_load_string(removeNamespaceFromXML($xml))), true);
}

通过调用 namespacedXMLToArray() 函数,我可以简单地获得一个 100% 适合我的数组。

希望这种方法可以帮助其他人。我敢肯定,如果您不知道存在哪些可能的命名空间,您可以使用正则表达式来查找各种已定义的命名空间,然后在知道它们的名称后将其删除。

【讨论】:

  • 感谢这似乎工作。我用我的命名空间替换了 toRemove 数组中的元素,它似乎正在工作。
猜你喜欢
  • 2019-11-19
  • 2014-06-09
  • 2015-08-15
  • 2012-05-18
  • 1970-01-01
  • 2019-11-26
  • 1970-01-01
  • 1970-01-01
  • 2018-06-27
相关资源
最近更新 更多