【问题标题】:parse XML with simplexml_load_string()使用 simplexml_load_string() 解析 XML
【发布时间】:2019-12-05 17:46:38
【问题描述】:

我有以下来自我必须使用的 API 的 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 $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 Parser 处理一些响应,而 simplexml_load_string() 用于其他不太容易维护的响应。

这里的问题是:有没有办法使用simplexml_load_string() 来解析这两种响应类型?还是我应该切换到 XML Parser 或 DOMDocument 或其他类似的库?

注意:从第一个 XML sn-p 开始,我只对从 NewDataSet 节点提取内容感兴趣。

如果您需要更多详细信息,请告诉我。任何帮助表示赞赏。

【问题讨论】:

    标签: php xml xml-parsing


    【解决方案1】:

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

    改用这个:

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

    【讨论】:

    • 感谢您的回答。我真正需要回答的问题是:这可以通过simplexml_load_string() 实现吗?我已经设法解析它并使用 XML Parser 使用详细信息。您的解决方案有效,但没有回答我的问题。
    • 确实返回“有效 XML”。这可能正是因为diffgr:diffgramNewDataSet 节点子节点。所以,XML 是有效的。是否可以使用simplexml_load_string() 解析它?测试 XML 的 var_dumped 响应为:object(SimpleXMLElement)[917] 执行时:var_dump simplexml_load_string( $xml );
    • 祝你好运。如果您有非常复杂的 xml 文件,simplexml_* 会有点“受限”。我会推荐使用DOMDocument,因为有更好的命名空间支持。
    • 我设法使用另一个问题来做到这一点。无论如何感谢您的帮助!由于遗留代码,我被困在这个库中。它很快就会被重写,但现在需要这样做。
    【解决方案2】:

    解决方案是不使用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
            (
            )
    
    )
    

    感谢您的帮助!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-02-18
      • 2011-04-16
      • 1970-01-01
      • 1970-01-01
      • 2011-02-23
      相关资源
      最近更新 更多