使用simplexml_load_string()解析XML

时间:2019-07-27 20:55:36

标签: php xml xml-parsing

我有以下xml数据集,它们来自我必须使用的API:

<?xml version="1.0" encoding="utf-8"?>
<DataSet xmlns="http://examplesite.com/WebRes">
  <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="BuildingInfo">
            <xs:complexType>
              <xs:sequence>
                <xs:element name="ID_Building" type="xs:int" minOccurs="0" />
                <xs:element name="Name" type="xs:string" minOccurs="0" />
                <xs:element name="Description" 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="">
      <BuildingInfo diffgr:id="BuildingInfo1" msdata:rowOrder="0">
        <ID_Building>333</ID_Building>
        <Name>Example Building Name</Name>
        <Description />
      </BuildingInfo>
    </NewDataSet>
    <NewDataSet xmlns="">
      <BuildingInfo diffgr:id="BuildingInfo1" msdata:rowOrder="0">
        <ID_Building>334</ID_Building>
        <Name>Example Building Name2</Name>
        <Description />
      </BuildingInfo>
    </NewDataSet>
  </diffgr:diffgram>
</DataSet>

这个问题是,如果我执行以下操作:

<?php $result = simplexml_load_string( $xml, 'SimpleXMLElement', 0, 'xs' );

echo ($result ? 'Valid XML' : 'Parse Error'), PHP_EOL;
print_r( $result );

结果是:

Parse Error
SimpleXMLElement Object
(
)

作为后备解决方案,我使用了:

$p = xml_parser_create();
xml_parse_into_struct( $p, $xml, $result, $index );
xml_parser_free( $p );

哪个工作正常。

另一个问题是,从相同的API我也有这样的响应:

<?xml version="1.0" encoding="utf-8"?>
<ArrayOfRoomTypeBuildingsDetails xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://examplesite.com/WebRes">
  <RoomTypeBuildingsDetails>
    <ID_RoomType>123</ID_RoomType>
    <RoomTypeName>Post Name</RoomTypeName>
    <RoomTypeDescription>This is the description</RoomTypeDescription>
    <GuestMax>2</GuestMax>
  </RoomTypeBuildingsDetails>
</ArrayOfRoomTypeBuildingsDetails>

simplexml_load_string()函数完美配合。这意味着我将XML解析器用于某些响应,将simplexml_load_string()用于其他响应,这不太容易维护。

这里的问题是:有什么方法可以使用simplexml_load_string()解析两种响应类型?还是应该只切换到XML Parser或DOMDocument或其他类似的库?

注意::从第一个XML代码段开始,我只想从NewDataSet节点提取内容。

让我知道是否需要更多详细信息。任何帮助表示赞赏。

2 个答案:

答案 0 :(得分:1)

请小心检查解析错误。空的SimpleXMLElement可以解析为false,并且如果您的XML不包含文本或仅包含命名空间元素,则您的错误检查可能是错误的。检查解析错误时,请始终使用=== false

改为使用此:

echo ($result !== false ? 'Valid XML' : 'Parse Error'), PHP_EOL;

答案 1 :(得分:0)

解决方案是不使用simplexml_load_string(),而是通过创建新的SimpleXMLElement进行解析。它仍然没有使用simplexml_load_string(),但允许我使用SimpleXMLElement来处理它。

我的测试XML

<?xml version="1.0" encoding="utf-8"?>
<DataSet xmlns="http://examplesite.com/WebRes">
  <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="BuildingInfo">
            <xs:complexType>
              <xs:sequence>
                <xs:element name="ID_Building" type="xs:int" minOccurs="0" />
                <xs:element name="Name" type="xs:string" minOccurs="0" />
                <xs:element name="Description" 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="">
      <BuildingInfo diffgr:id="BuildingInfo1" msdata:rowOrder="0">
        <ID_Building>333</ID_Building>
        <Name>Example Building Name</Name>
        <Description />
      </BuildingInfo>
    </NewDataSet>
    <NewDataSet xmlns="">
      <BuildingInfo diffgr:id="BuildingInfo1" msdata:rowOrder="0">
        <ID_Building>334</ID_Building>
        <Name>Example Building Name2</Name>
        <Description />
      </BuildingInfo>
    </NewDataSet>
  </diffgr:diffgram>
</DataSet>

我的PHP代码

$sxe = new SimpleXMLElement($quote_response);
$sxe->registerXPathNamespace('d', 'urn:schemas-microsoft-com:xml-diffgram-v1');
$result = $sxe->xpath("//NewDataSet");

echo "<pre>";
foreach ($result[0] as $title) {
    print_r($title);
}
echo "</pre>";

结果

SimpleXMLElement Object
(
    [ID_Building] => 333
    [Name] => Example Building Name
    [Description] => SimpleXMLElement Object
        (
        )

)

感谢您的帮助!