simplexml 相关问题

主源代码树附带的PHP扩展。 SimpleXML扩展提供了一个非常简单且易于使用的工具集,用于将XML转换为可以使用普通属性选择器和数组迭代器处理的对象。对于Java“Simple”XML框架,请使用[simple-framework]标签。

PHP - SimpleXMLElement 未使用名称空间正确解析

这是由API返回的: 这是由 API 返回的: <?xml version='1.0' encoding='utf-8'?> <entry xmlns="http://www.w3.org/2005/Atom" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xml:base="https://exmple.com/odata/"> <id>https://example.com/odata/PicklistOption(989L)</id> <title type="text" /> <updated>2015-09-03T11:56:51Z</updated> <author> <name /> </author> <link rel="edit" title="PicklistOption" href="PicklistOption(989L)" /> <link rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/childPicklistOptions" type="application/atom+xml;type=feed" title="childPicklistOptions" href="PicklistOption(989L)/childPicklistOptions" /> <link rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/parentPicklistOption" type="application/atom+xml;type=entry" title="parentPicklistOption" href="PicklistOption(989L)/parentPicklistOption" /> <link rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/picklistLabels" type="application/atom+xml;type=feed" title="picklistLabels" href="PicklistOption(989L)/picklistLabels" /> <link rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/picklist" type="application/atom+xml;type=entry" title="picklist" href="PicklistOption(989L)/picklist" /> <category term="SFOData.PicklistOption" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" /> <content type="application/xml"> <m:properties> <d:id m:type="Edm.Int64">989</d:id> <d:status>ACTIVE</d:status> <d:sortOrder m:type="Edm.Int32">229</d:sortOrder> <d:minValue m:type="Edm.Double">-1</d:minValue> <d:externalCode>PL</d:externalCode> <d:optionValue m:type="Edm.Double">-1</d:optionValue> <d:maxValue m:type="Edm.Double">-1</d:maxValue> </m:properties> </content> </entry> 现在正在努力获得<d:id> $xml = new SimpleXMLElement($xmlstr); $namespaces = $xml->getNameSpaces(true); $xml->registerXPathNamespace('m', $namespaces['m']); $xml->registerXPathNamespace('d', $namespaces['d']); $id = $xml->xpath('/entry/content/m:properties/d:id'); var_dump($id); 但我明白了array(0)。 不要从文档中获取命名空间。在您的应用程序中定义它们。命名空间是 xmlns/xmlns:* 属性的值。 xmlns 属性是默认命名空间。所以标签 entry 实际上是 {http://www.w3.org/2005/Atom}:entry。 命名空间必须是唯一的。为了避免冲突,大多数人使用 URL。 (其他人不太可能使用您的域来定义他们的命名空间。)这样做的缺点是命名空间是带有特殊字符的大字符串。这是通过使用命名空间前缀作为别名来解决的。 Xpath 没有默认的命名空间。您需要为您喜欢使用的每个命名空间注册一个前缀。 Xpath 引擎会将前缀解析为实际名称空间,并将其与节点解析的名称空间进行比较。 $xml = new SimpleXMLElement($xmlstr); $namespaces = [ 'a' => 'http://www.w3.org/2005/Atom', 'm' => 'http://schemas.microsoft.com/ado/2007/08/dataservices/metadata', 'd' => 'http://schemas.microsoft.com/ado/2007/08/dataservices', 'o' => 'https://exmple.com/odata/' ]; foreach ($namespaces as $prefix => $namespace) { $xml->registerXPathNamespace($prefix, $namespace); } $id = $xml->xpath('/a:entry/a:content/m:properties/d:id'); var_dump($id); 输出: array(1) { [0]=> object(SimpleXMLElement)#2 (0) { } } 您必须再次在每个 SimpleXMLElement 上注册 Xpath 命名空间。 这在 DOM 中更方便。 DOMXpath::evaluate() 执行 Xpath 表达式,并可以返回节点列表或标量,具体取决于表达式。 $document = new DOMDocument($xmlstr); $document->loadXml($xmlstr); $xpath = new DOMXpath($document); $namespaces = [ 'a' => 'http://www.w3.org/2005/Atom', 'm' => 'http://schemas.microsoft.com/ado/2007/08/dataservices/metadata', 'd' => 'http://schemas.microsoft.com/ado/2007/08/dataservices', 'o' => 'https://exmple.com/odata/' ]; foreach ($namespaces as $prefix => $namespace) { $xpath->registerNamespace($prefix, $namespace); } $id = $xpath->evaluate('string(/a:entry/a:content/m:properties/d:id)'); var_dump($id); 输出: string(3) "989" 这是如何通过节点元素方法完成的,例如 $xml->内容->属性->id ?

回答 2 投票 0

SimpleXML 返回 0 元素

我从 Soap 请求中获取响应,并将其传递到新的 SimpleXML 构造中。 $response = $this->client->$method(array("Request" => $this->params)); $response_string = $t...

回答 2 投票 0

从 SimpleXML 填充二维数组,然后按第一列排序[重复]

我有一个产品 xml,其中包含多个价格不同的卖家。在浏览 simpleXML 对象并将其放入数组中之后,我需要以某种方式对数组进行排序。 循环遍历 xml 文件: 前...

回答 1 投票 0

从 simplexml 排序和数组[重复]

我有一个productxml,其中包含多个价格不同的卖家。在浏览 simplexml 对象并将其放入数组中之后,我需要以某种方式对数组进行排序。 循环遍历 xml 文件:

回答 1 投票 0

使用 SimpleXML 删除 XML 文档元素

我有以下代码: 能量 蛋白质 脂肪 我有以下代码: <nutrition> <code> <lol1>energy</lol1> <lol2>protein</lol2> <lol3>fat</lol3> </code> </nutrition> 我想要: <code> <lol1>energy</lol1> <lol2>protein</lol2> <lol3>fat</lol3> </code> 是否有任何 SimpleXML 函数可以删除文档元素? 我知道有一些 DOM 库,但我不想使用它 在 PHP SimpleXML 中重命名文档元素在技术上是不可能的。 实际上你也不能用 DOMDocument 重命名它。但与 SimpleXML 不同的是,您可以轻松地使用 DOMDocument::replaceChild 替换元素。 使用给定的输入: $buffer = <<<XML <nutrition> <code> <lol1>energy</lol1> <lol2>protein</lol2> <lol3>fat</lol3> </code> </nutrition> XML; 首先创建DOMDocument: $doc = new DOMDocument(); $doc->preserveWhiteSpace = false; $doc->formatOutput = true; 然后在此处加载您的 XML(例如作为字符串 $buffer): $doc->loadXML($buffer); 获取即将成为文档元素: $code = $doc->documentElement->getElementsByTagName('*')->item(0); 替换文档元素和输出以显示其有效: $doc->replaceChild($code, $doc->documentElement); $doc->save('php://output'); 这给出了以下输出: <?xml version="1.0"?> <code> <lol1>energy</lol1> <lol2>protein</lol2> <lol3>fat</lol3> </code> 就是这样。即使您似乎不喜欢 DOMDocument,希望这仍然有帮助。但不要害怕,它是 SimpleXMLElement 的姐妹库。 是的,您可以: $xmlstr = <<<'XML' <nutrition> <code> <lol1>energy</lol1> <lol2>protein</lol2> <lol3>fat</lol3> </code> </nutrition> XML; $xml = new SimpleXMLElement($xmlstr); foreach ($xml->xpath('/nutrition/child::code[1]') as $node) { $unwrappedXml = new \SimpleXMLElement($node->asXML()); break; } echo $unwrappedXml->asXML();

回答 2 投票 0

使用 PHP 的 SimpleXML 检测空 XML 节点

首先我要说的是,我不熟悉解析 XML 和/或编写 PHP。我一直在研究和拼凑我正在做的事情,但我陷入了困境。 我正在尝试创建一个基本的...

回答 4 投票 0

使用 SimpleXML 和 jQuery Ajax 在服务器中创建 XML 文件

我想做的事情肯定可以完成,但我做错了:我想在使用 Ajax 调用时创建一个 XML 文件。我得到了以下代码(合成的)。也许这个例子不...

回答 2 投票 0

父项外部的 XML 节点

使用这篇文章中提供的代码在.xml 上分割节点。如下所示,当我通过添加“颜色”来扩展字符串时,它将结果放置在父项节点之外 使用本文中提供的代码在 . 上进行 xml 分割节点,如下所示,当我通过添加“颜色”来扩展字符串时,它将结果放置在父项节点之外 <?php $xml_string = '<product><item><partno>abc123</partno><Compatbility>model1: 110C, 115C, 117C. model2: 1835C, 1840C. model3: 210C, 215C, 3240C.</Compatbility></item></product>'; $original_xml = simplexml_load_string($xml_string); $data = json_decode(json_encode($original_xml), true); $compatbility = $data['item']['Compatbility']; // get all compatibility values // explode values $compatbility = array_filter(array_map('trim', explode('.', $compatbility))); $new_xml = new SimpleXMLElement('<product/>'); // initialize new xml // add necessary values $new_xml->addChild('item')->addChild('partno', $data['item']['partno']); $new_xml->item->addChild('Compatbility'); // loop the values and add them as children foreach($compatbility as $value) { $value = trim(preg_replace('/(\w+):/', '', $value)); $new_xml->item->Compatbility->addChild('model', $value); } echo $new_xml->asXML(); // output as xml ?> 修改代码,为 xml 字符串添加颜色 <?php $xml_string = '<product><item><partno>abc123</partno><colour>black</colour><Compatbility>model1: 110C, 115C, 117C. model2: 1835C, 1840C. model3: 210C, 215C, 3240C.</Compatbility></item></product>'; $original_xml = simplexml_load_string($xml_string); $data = json_decode(json_encode($original_xml), true); $compatbility = $data['item']['Compatbility']; // get all compatibility values // explode values $compatbility = array_filter(array_map('trim', explode('.', $compatbility))); $new_xml = new SimpleXMLElement('<product/>'); // initialize new xml // add necessary values $new_xml->addChild('item')->addChild('partno', $data['item']['partno']); $new_xml->addChild ('colour', $data['item']['colour']); $new_xml->item->addChild('Compatbility'); // loop the values and add them as children foreach($compatbility as $value) { $value = trim(preg_replace('/(\w+):/', '', $value)); $new_xml->item->Compatbility->addChild('model', $value); } echo $new_xml->asXML(); // output as xml ?> 以及 XML 输出 <product> <item> <partno>abc123</partno> <Compatbility><model>110C, 115C, 117C</model> <model>1835C, 1840C</model> <model>210C, 215C, 3240C</model> </Compatbility> </item> <colour>black</colour> </product> 正如您所看到的,它被放置在 </item> 之后,而它应该位于 </item> 内部 产品 xml 文件有 650 个条目,所以我不确定这是否正确 希望这是足够的信息 - 谢谢 方法 SimpleXMLElement::addChild 适用于父元素。 例如在你的(不起作用)的例子中: $new_xml->addChild ('colour', $data['item']['colour']); 父元素位于 $new_xml 内。如果您不想将 <color> 子元素添加到该父元素,请选择其他元素作为父元素。最佳:选择正确的父元素。 访问 SimleXMLElement 是基本使用示例的一部分。 这里有一个关于如何使用 simplexml 将子元素添加到特定父元素的示例: <?php $xmlstr = <<<XML <?xml version='1.0' standalone='yes'?> <movies> <movie> <title>PHP: Behind the Parser</title> <characters> <character> <name>Ms. Coder</name> <actor>Onlivia Actora</actor> </character> <character> <name>Mr. Coder</name> <actor>El Act&#211;r</actor> </character> </characters> <plot> So, this language. It's like, a programming language. Or is it a scripting language? All is revealed in this thrilling horror spoof of a documentary. </plot> <great-lines> <line>PHP solves all my web problems</line> </great-lines> <rating type="thumbs">7</rating> <rating type="stars">5</rating> </movie> </movies> XML; $movies = new SimpleXMLElement($xmlstr); echo $movies->movie[0]->plot; # So, this language. It's like, a programming language. Or is it a ... $movie = $movies->movie[0]; $movie->addChild('color', 'technicolor'); # added color child to the move element

回答 1 投票 0

使用 PHP 读取 XML feed

我在尝试阅读和解析此提要时遇到问题: 一些 XML 提要 由于某种原因,函数 SimpleXMLElement 返回空节点。我正在使用 file_get_contents 读取 URL,然后

回答 1 投票 0

如何使用SimpleXmlElement编写CDATA?

我有以下代码来创建和更新 xml 文件: '); $xml->title = '站点标题'; $xml->标题->addAttri...

回答 5 投票 0

使用属性名称从 simplexml_load_string 中提取 xml 元素

我想从下面提到的属性名称(sm_field_base_url)或xpath上的XML bsed中提取sm_field_base_url。我怎样才能做到这一点。 我正在使用 simplexml_load_string() 来解析 xml

回答 1 投票 0

使用 php 构建 xml 并定义结构

我正在尝试创建一个具有以下结构的xml: 我正在尝试创建一个具有以下结构的 xml: <pt:request xmlns:pt="urn:logalty:schemas:core:1.0" xmlns:identity="urn:logalty:schemas:core:identity:1.0" xmlns:process_meta="urn:logalty:schemas:process:meta:1.0" xmlns:ptforms="urn:logalty:schemas:forms:1.0" xmlns:request_meta="urn:logalty:schemas:request:meta:1.0"> <pt:request_meta> <request_meta:service>PT0005_ACCEPTANCEXPRESS</request_meta:service> <request_meta:time2close unit="d" value="28"/> <request_meta:time2save unit="d" value="1825"/> <request_meta:lopd>0</request_meta:lopd> <request_meta:retryprotocol>3</request_meta:retryprotocol> <request_meta:synchronous>false</request_meta:synchronous> <request_meta:tsa>0</request_meta:tsa> <request_meta:userdefined name="LGT_SDKJava">4.13.2</request_meta:userdefined> </pt:request_meta> <pt:process_meta> <process_meta:generator>generator</process_meta:generator> <process_meta:language>es-ES</process_meta:language> <process_meta:receivers> <identity:receiver receiver-id="1"> <identity:personalData> <identity:firstname>first</identity:firstname> <identity:middlename>middle</identity:middlename> <identity:lastname1>last1</identity:lastname1> <identity:lastname2>last2</identity:lastname2> </identity:personalData> <identity:contact> <identity:uuid>uuid1</identity:uuid> <identity:phone>phone</identity:phone> <identity:mobile>mobile</identity:mobile> <identity:fax>fax</identity:fax> <identity:email>[email protected]</identity:email> </identity:contact> <identity:legalIdentity> <identity:type>DNI</identity:type> <identity:jurisdictionCountry>ESP</identity:jurisdictionCountry> <identity:issuer>issuer</identity:issuer> <identity:id>id</identity:id> <identity:certificate>certificate</identity:certificate> </identity:legalIdentity> <identity:binarycontentrules> <identity:binarycontentrule binary-content-group-id="1" binarycontentrule-id="1"> <request_meta:signMethods> <request_meta:signMethod>SMS_VOICE</request_meta:signMethod> </request_meta:signMethods> </identity:binarycontentrule> </identity:binarycontentrules> </identity:receiver> </process_meta:receivers> <process_meta:subject>subject</process_meta:subject> <process_meta:body>body</process_meta:body> <process_meta:url>LOGALTY_DIRECT_ACCESS_DOC_IN_FRAME</process_meta:url> <process_meta:email>[email protected]</process_meta:email> <process_meta:userdefined name="name">value</process_meta:userdefined> </pt:process_meta> 但我的问题是,在数组中的所有键中,我的代码添加了 pt,我不知道为什么。 我的结果: <?xml version="1.0"?> <pt:request xmlns:pt="urn:logalty:schemas:core:1.0" xmlns:identity="urn:logalty:schemas:core:identity:1.0" xmlns:process_meta="urn:logalty:schemas:process:meta:1.0" xmlns:ptforms="urn:logalty:schemas:forms:1.0" xmlns:request_meta="urn:logalty:schemas:request:meta:1.0"> <pt:request_meta> <pt:service>instalacion_id_1</pt:service> <pt:time2close unit="d" value="28"/> <pt:time2save unit="d" value="1825"/> <pt:lopd>0</pt:lopd> <pt:retryprotocol>3</pt:retryprotocol> <pt:synchronous/> <pt:tsa>0</pt:tsa> <pt:userdefined name="php">8.1.6</pt:userdefined> </pt:request_meta> <pt:process_meta> <pt:generator>generator</pt:generator> <pt:language>es-ES</pt:language> <pt:receivers> <pt:receiver receiver-id="1"> <pt:personalData> <pt:firstname>first</pt:firstname> <pt:middlename>middle</pt:middlename> <pt:lastname1>last1</pt:lastname1> <pt:lastname2>last2</pt:lastname2> </pt:personalData> <pt:contact> <pt:uuid>uuid1</pt:uuid> <pt:phone>phone</pt:phone> <pt:mobile>mobile</pt:mobile> <pt:fax>fax</pt:fax> <pt:email>[email protected]</pt:email> </pt:contact> <pt:legalIdentity> <pt:type>DNI</pt:type> <pt:jurisdictionCountry>ESP</pt:jurisdictionCountry> <pt:issuer>issuer</pt:issuer> <pt:id>id</pt:id> <pt:certificate>certificate</pt:certificate> </pt:legalIdentity> <pt:binarycontentrules> <pt:binarycontentrule binary-content-group-id="1" binarycontentrule-id="1"> <pt:signMethods> <pt:signMethod>SMS_VOICE</pt:signMethod> </pt:signMethods> </pt:binarycontentrule> </pt:binarycontentrules> </pt:receiver> </pt:receivers> <pt:subject>subject</pt:subject> <pt:body>body</pt:body> <pt:url>LOGALTY_DIRECT_ACCESS_DOC_IN_FRAME</pt:url> <pt:email>[email protected]</pt:email> <pt:userdefined name="name">value</pt:userdefined> </pt:process_meta> </pt:request> 我的数组,其数据: $logalty_data_header = [ 'request_meta:service' => 'instalacion_id_'.$id, 'request_meta:time2close unit="d" value="28"' => "", 'request_meta:time2save unit="d" value="1825"' => "", 'request_meta:lopd' => 0, 'request_meta:retryprotocol' => 3, 'request_meta:synchronous' => false, 'request_meta:tsa' => 0, 'request_meta:userdefined name="php"' => '8.1.6', ]; $logalty_data_process = array( 'process_meta:generator' => 'generator', 'process_meta:language' => 'es-ES', 'process_meta:receivers' => array( 'identity:receiver receiver-id="1"' => array( 'identity:personalData' => array( 'identity:firstname' => 'first', 'identity:middlename' => 'middle', 'identity:lastname1' => 'last1', 'identity:lastname2' => 'last2', ), 'identity:contact' => array( 'identity:uuid' => 'uuid1', 'identity:phone' => 'phone', 'identity:mobile' => 'mobile', 'identity:fax' => 'fax', 'identity:email' => '[email protected]', ), 'identity:legalIdentity' => array( 'identity:type' => 'DNI', 'identity:jurisdictionCountry' => 'ESP', 'identity:issuer' => 'issuer', 'identity:id' => 'id', 'identity:certificate' => 'certificate', ), 'identity:binarycontentrules' => array( 'identity:binarycontentrule binary-content-group-id="1" binarycontentrule-id="1"' => array( "request_meta:signMethods" => array( "request_meta:signMethod" => "SMS_VOICE", ) ) ) ) ), 'process_meta:subject' => 'subject', 'process_meta:body' => 'body', 'process_meta:url' => 'LOGALTY_DIRECT_ACCESS_DOC_IN_FRAME', 'process_meta:email' => '[email protected]', 'process_meta:userdefined name="name"' => 'value', ); 我的类中有一个函数,用于创建我的 xml 文件,我正在发送或 $logalty_data_header 或 $logalty_data_process 在我的课堂上我有: public function array_to_xml($data_header, $data_process, $path = null, $rootElement = null, $xml = null) { $_xml = $xml; // If there is no Root Element then insert root if ($_xml === null) { $xml = new \SimpleXMLElement($rootElement !== null ? $rootElement : '<pt:request xmlns:pt="urn:logalty:schemas:core:1.0" xmlns:identity="urn:logalty:schemas:core:identity:1.0" xmlns:process_meta="urn:logalty:schemas:process:meta:1.0" xmlns:ptforms="urn:logalty:schemas:forms:1.0" xmlns:request_meta="urn:logalty:schemas:request:meta:1.0"></pt:request>'); } $wrapper = $xml->addChild('pt:request_meta'); // Visit all key value pair foreach ($data_header as $k => $v) { // If there is nested array then if (is_array($v)) { // Call function for nested array $this->array_to_xml($v, $k, $wrapper->addChild($k)); }else { // Simply add child element. $wrapper->addChild($k, $v); } } $wrapper2 = $xml->addChild('pt:process_meta'); $this->processData($data_process, $xml, $wrapper2); return $xml->asXML($path.'/installation.xml'); } 在我的函数中processData我有一个: private function processData($data_process, $xml, $wrapper2) { foreach ($data_process as $k => $v) { // If there is nested array then if (is_array($v)) { // Call function for nested array $this->processData($v, $k, $wrapper2->addChild($k)); }else { // Simply add child element. $wrapper2->addChild($k, $v); } } } 我认为我的错误在于array_to_xml,但我不知道我的错误在哪里。这个 xml,用于将其发送到 API,需要使用第一种格式创建。 谢谢你的自述,抱歉我的英语不好 试试这个 $logalty_data_header = [ 'request_meta:service' => 'instalacion_id_' . $id, 'request_meta:time2close unit="d" value="28"' => "", 'request_meta:time2save unit="d" value="1825"' => "", 'request_meta:lopd' => 0, 'request_meta:retryprotocol' => 3, 'request_meta:synchronous' => false, 'request_meta:tsa' => 0, 'request_meta:userdefined name="php"' => '8.1.6', ]; $logalty_data_process = array( 'process_meta:generator' => 'generator', 'process_meta:language' => 'es-ES', 'process_meta:receivers' => array( 'identity:receiver receiver-id="1"' => array( 'identity:personalData' => array( 'identity:firstname' => 'first', 'identity:middlename' => 'middle', 'identity:lastname1' => 'last1', 'identity:lastname2' => 'last2', ), // ... other nested data ) ), // ... other process data ); // Create a new XML document $xml = new DOMDocument('1.0', 'utf-8'); $xml->formatOutput = true; // Enable formatting for readability // Create the root element with namespaces $root = $xml->createElementNS('urn:logalty:schemas:core:1.0', 'pt:request'); $root->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:identity', 'urn:logalty:schemas:core:identity:1.0'); $root->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:process_meta', 'urn:logalty:schemas:process:meta:1.0'); $root->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:ptforms', 'urn:logalty:schemas:forms:1.0'); $root->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:request_meta', 'urn:logalty:schemas:request:meta:1.0'); $xml->appendChild($root); // Create request_meta element and its children $requestMeta = $xml->createElement('request_meta'); $root->appendChild($requestMeta); createXmlChildren($xml, $requestMeta, $logalty_data_header); // Create process_meta element and its children $processMeta = $xml->createElement('process_meta'); $root->appendChild($processMeta); createXmlChildren($xml, $processMeta, $logalty_data_process); // Function to create nested XML elements recursively function createXmlChildren($xml, $parent, $data) { foreach ($data as $key => $value) { $parts = explode(':', $key); $tagName = $parts[count($parts) - 1]; $element = $xml->createElement($tagName); $parent->appendChild($element); if (is_array($value)) { createXmlChildren($xml, $element, $value); } else { $element->textContent = $value; } // Handle attributes if present if (count($parts) > 1) { $attributes = array_slice($parts, 0, -1); foreach ($attributes as $attribute) { $name = explode('=', $attribute)[0]; $value = explode('=', $attribute)[1]; $element->setAttribute($name, $value); } } } } // Save the XML to a file or output it $xml->save('output.xml'); // Save to a file // echo $xml->saveXML(); //

回答 1 投票 0

使用 SimpleXMLElement 从 php 数组创建 xml 文件

我正在尝试使用 laravel 和 SimpleXMLElement 创建一个完整的 XML 文件。 我读到我可以从关联数组构建这个文件,我正在尝试它。我需要创建这个 xml 来发送这个 f...

回答 1 投票 0

没有子元素的元素不显示 SimpleXml 属性

我有以下 XML: 我有以下 XML: <?xml version="1.0"?> <STATUS_LIST> <ORDER_STATUS SORDER_CODE="SO001" ASSOCIATED_REF="001"> <INVOICES> <INVOICE INVOICE_CODE="???">SOMETHING</INVOICE> </INVOICES> </ORDER_STATUS> </STATUS_LIST> 当我运行以下代码时: $statuses = simplexml_load_string($result); //Where $result is my XML if (!empty($statuses)) { foreach ($statuses as $status) { foreach ($status->INVOICES as $invoice) { echo (string)$invoice->attributes()->INVOICE_CODE; } } } 我单步执行此代码,我可以看到针对ORDER_STATUS的属性,但我无法看到针对INVOICE的属性。不过,我可以看到发票上的价值 SOMETHING。 知道什么可能导致这种情况吗? 更新 经过一些测试,如果我将元素添加到 INVOICE 元素中,我可以获得显示的属性,因此如果我使用此 xml 来代替,它将起作用: <?xml version="1.0"?> <STATUS_LIST> <ORDER_STATUS SORDER_CODE="SO001" ASSOCIATED_REF="001"> <INVOICES> <INVOICE INVOICE_CODE="???"><TEST>tester</TEST></INVOICE> </INVOICES> </ORDER_STATUS> </STATUS_LIST> 所以它有里面有一个元素来获取属性!? 根据过去的问题,“SimpleXML 不允许在同一元素上使用属性和文本。”这非常荒谬,我找不到任何关于这一事实的官方报道,但这似乎是真的。瘸。这是有效的 XML。我知道 Perl SimpleXML 读起来很好。 您的问题与没有内容的元素无关,您只是循环定义稍有错误。 当您编写 foreach ($status->INVOICES as $invoice) 时,SimpleXML 将循环遍历 $status 元素的每个子元素(称为 INVOICES);在这种情况下,总会有一个这样的元素。但您真正想要的是循环该元素的所有 children - 各个 INVOICE 节点。 为此,您可以使用以下方法之一: foreach ($status->INVOICES->children() as $invoice)(循环遍历第一个元素的所有子节点,在本例中仅循环 INVOICES 元素) foreach ($status->INVOICES[0]->children() as $invoice)(相同,但更明确地选择第一个 INVOICES 节点) foreach ($status->INVOICES[0] as $invoice)(实际上又做了同样的事情:因为您专门选择了一个节点,然后要求循环,SimpleXML 假设您想要它的子节点;这就是为什么 foreach($statuses as $status) 用作外循环) foreach ($status->INVOICES->INVOICE as $invoice)(仅循环名为 INVOICE 的子节点,恰好是所有子节点) 就个人而言,我会重写您的示例循环如下: foreach ($statuses->ORDER_STATUS as $status) { foreach ($status->INVOICES->INVOICE as $invoice) { echo (string)$invoice['INVOICE_CODE']; } } 这里有一个现场演示来证明它是有效的。 记录在案(PHP 8.1) $xml='<?xml version="1.0"?> <STATUS_LIST> <ORDER_STATUS SORDER_CODE="SO001" ASSOCIATED_REF="001"> <INVOICES> <INVOICE INVOICE_CODE="???">SOMETHING</INVOICE> </INVOICES> </ORDER_STATUS> </STATUS_LIST>'; $statuses = simplexml_load_string($xml); var_dump($statuses) 结果: object(SimpleXMLElement)#1 (1) { ["ORDER_STATUS"]=> object(SimpleXMLElement)#2 (2) { ["@attributes"]=> array(2) { ["SORDER_CODE"]=> string(5) "SO001" ["ASSOCIATED_REF"]=> string(3) "001" } ["INVOICES"]=> object(SimpleXMLElement)#3 (1) { ["INVOICE"]=> string(9) "SOMETHING" } } } 属性发票 INVOICE_CODE="???"不可用。 所以@Dan Goodspeed 是对的 解决方案: 补丁?不,它已经坏了很多年了。 regexp 改变字符串?是的,但它改变了结果的语义 $str = preg_replace('/<([^ ]+) ([^>]*)>([^<>]*)<\/\\1>/i', '<$1 $2><value>$3</value></$1>', $string);

回答 3 投票 0

获取XML字符串中二级标签的名称

我正在尝试从 XML 文件获取数据并将其转换为 JSON。 $xml = simplexml_load_file('types.xml','SimpleXMLElement',LIBXML_NOCDATA); $json = json_encode($xml); $array = json_decode(...

回答 2 投票 0

查询数组名称

有一个非常愚蠢的时刻.. 我正在尝试从 XML 文件获取数据并将其转换为 JSON $xml = simplexml_load_file('types.xml','SimpleXMLElement',LIBXML_NOCDATA); $json = json_encode($...

回答 1 投票 0

如何防止 php simplexml 中的自关闭标签

我想使用php simplexml生成xml。 $xml = new SimpleXMLElement(''); $output = $xml->addChild('child1'); $output->addChild('child2', "value"); $output->addChild('n...

回答 6 投票 0

如何在PHP中使用XMLReader?

我有以下 XML 文件,该文件相当大,我无法让 simplexml 打开并读取该文件,所以我尝试 XMLReader 但在 php 中没有成功 我有以下 XML 文件,该文件相当大,我无法使用 simplexml 打开和读取该文件,所以我尝试使用 XMLReader,但在 php 中没有成功 <?xml version="1.0" encoding="ISO-8859-1"?> <products> <last_updated>2009-11-30 13:52:40</last_updated> <product> <element_1>foo</element_1> <element_2>foo</element_2> <element_3>foo</element_3> <element_4>foo</element_4> </product> <product> <element_1>bar</element_1> <element_2>bar</element_2> <element_3>bar</element_3> <element_4>bar</element_4> </product> </products> 不幸的是,我没有找到关于 PHP 的好的教程,并且很想看看如何将每个元素内容存储在数据库中。 这一切都取决于工作单元有多大,但我猜你正在尝试连续处理每个<product/>节点。 为此,最简单的方法是使用 XMLReader 获取每个节点,然后使用 SimpleXML 访问它们。这样,您可以保持较低的内存使用量,因为您一次处理一个节点,并且仍然可以利用 SimpleXML 的易用性。例如: $z = new XMLReader; $z->open('data.xml'); $doc = new DOMDocument; // move to the first <product /> node while ($z->read() && $z->name !== 'product'); // now that we're at the right depth, hop to the next <product/> until the end of the tree while ($z->name === 'product') { // either one should work //$node = new SimpleXMLElement($z->readOuterXML()); $node = simplexml_import_dom($doc->importNode($z->expand(), true)); // now you can use $node without going insane about parsing var_dump($node->element_1); // go to next <product /> $z->next('product'); } 快速概述不同方法的优缺点: 仅限 XMLReader 优点:速度快,占用内存小 缺点:编写和调试非常困难,需要大量用户态代码来完成任何有用的事情。用户态代码速度慢且容易出错。另外,它还让您需要维护更多行代码 XMLReader + SimpleXML 优点:不占用太多内存(仅处理一个节点所需的内存),而且 SimpleXML 顾名思义,非常易于使用。 缺点:为每个节点创建 SimpleXMLElement 对象不是很快。您确实必须对其进行基准测试才能了解这对您来说是否是一个问题。不过,即使是一台普通的机器也能够每秒处理一千个节点。 XMLReader + DOM 优点:使用与 SimpleXML 一样多的内存,并且 XMLReader::expand() 比创建新的 SimpleXMLElement 更快。我希望可以使用 simplexml_import_dom() 但在这种情况下似乎不起作用 缺点:DOM 使用起来很烦人。它介于 XMLReader 和 SimpleXML 之间。不像 XMLReader 那样复杂和尴尬,但与使用 SimpleXML 相差甚远。 我的建议:使用 SimpleXML 编写原型,看看它是否适合您。如果性能至关重要,请尝试 DOM。尽可能远离 XMLReader。请记住,您编写的代码越多,引入错误或引入性能回归的可能性就越高。 对于使用属性格式化的 xml... 数据.xml: <building_data> <building address="some address" lat="28.902914" lng="-71.007235" /> <building address="some address" lat="48.892342" lng="-75.0423423" /> <building address="some address" lat="58.929753" lng="-79.1236987" /> </building_data> php代码: $reader = new XMLReader(); if (!$reader->open("data.xml")) { die("Failed to open 'data.xml'"); } while($reader->read()) { if ($reader->nodeType == XMLReader::ELEMENT && $reader->name == 'building') { $address = $reader->getAttribute('address'); $latitude = $reader->getAttribute('lat'); $longitude = $reader->getAttribute('lng'); } $reader->close(); 我的 XML 解析生涯的大部分时间都花在从大量 XML (Amazon MWS) 中提取有用信息。因此,我的回答假设您只需要特定信息并且您知道它位于哪里。 我发现使用 XMLReader 最简单的方法是知道我想要从哪些标签中获取信息并使用它们。如果您了解 XML 的结构并且它有很多独特的标签,我发现使用第一种情况很容易。案例 2 和 3 只是向您展示如何针对更复杂的标签完成此操作。这是非常快的;我在 PHP 中最快的 XML 解析器是什么? 上讨论了速度 在进行这样的基于标签的解析时要记住的最重要的事情是使用 if ($myXML->nodeType == XMLReader::ELEMENT) {... - 它检查以确保我们只处理打开节点而不是空格或关闭节点或其他任何东西。 function parseMyXML ($xml) { //pass in an XML string $myXML = new XMLReader(); $myXML->xml($xml); while ($myXML->read()) { //start reading. if ($myXML->nodeType == XMLReader::ELEMENT) { //only opening tags. $tag = $myXML->name; //make $tag contain the name of the tag switch ($tag) { case 'Tag1': //this tag contains no child elements, only the content we need. And it's unique. $variable = $myXML->readInnerXML(); //now variable contains the contents of tag1 break; case 'Tag2': //this tag contains child elements, of which we only want one. while($myXML->read()) { //so we tell it to keep reading if ($myXML->nodeType == XMLReader::ELEMENT && $myXML->name === 'Amount') { // and when it finds the amount tag... $variable2 = $myXML->readInnerXML(); //...put it in $variable2. break; } } break; case 'Tag3': //tag3 also has children, which are not unique, but we need two of the children this time. while($myXML->read()) { if ($myXML->nodeType == XMLReader::ELEMENT && $myXML->name === 'Amount') { $variable3 = $myXML->readInnerXML(); break; } else if ($myXML->nodeType == XMLReader::ELEMENT && $myXML->name === 'Currency') { $variable4 = $myXML->readInnerXML(); break; } } break; } } } $myXML->close(); } 接受的答案给了我一个良好的开端,但带来了比我想要的更多的课程和更多的处理;所以这是我的解释: $xml_reader = new XMLReader; $xml_reader->open($feed_url); // move the pointer to the first product while ($xml_reader->read() && $xml_reader->name != 'product'); // loop through the products while ($xml_reader->name == 'product') { // load the current xml element into simplexml and we’re off and running! $xml = simplexml_load_string($xml_reader->readOuterXML()); // now you can use your simpleXML object ($xml). echo $xml->element_1; // move the pointer to the next product $xml_reader->next('product'); } // don’t forget to close the file $xml_reader->close(); Simple example: public function productsAction() { $saveFileName = 'ceneo.xml'; $filename = $this->path . $saveFileName; if(file_exists($filename)) { $reader = new XMLReader(); $reader->open($filename); $countElements = 0; while($reader->read()) { if($reader->nodeType == XMLReader::ELEMENT) { $nodeName = $reader->name; } if($reader->nodeType == XMLReader::TEXT && !empty($nodeName)) { switch ($nodeName) { case 'id': var_dump($reader->value); break; } } if($reader->nodeType == XMLReader::END_ELEMENT && $reader->name == 'offer') { $countElements++; } } $reader->close(); exit(print('<pre>') . var_dump($countElements)); } } XMLReader 在 PHP 站点 上有详细记录。这是一个 XML Pull 解析器,这意味着它用于迭代给定 XML 文档的节点(或 DOM 节点)。例如,您可以像这样浏览您提供的整个文档: <?php $reader = new XMLReader(); if (!$reader->open("data.xml")) { die("Failed to open 'data.xml'"); } while($reader->read()) { $node = $reader->expand(); // process $node... } $reader->close(); ?> 然后由您决定如何处理 XMLReader::expand()返回的节点。 试试这个 https://pear.php.net/package/XML_Serializer/docs/latest/XML_Serializer/XML_Unserializer.html 缺点:它占用大量内存。 优点:它读取 XML 并将其转换为多维数组。再简单不过了:) 这对我来说效果更好更快 <html> <head> <script> function showRSS(str) { if (str.length==0) { document.getElementById("rssOutput").innerHTML=""; return; } if (window.XMLHttpRequest) { // code for IE7+, Firefox, Chrome, Opera, Safari xmlhttp=new XMLHttpRequest(); } else { // code for IE6, IE5 xmlhttp=new ActiveXObject("Microsoft.XMLHTTP"); } xmlhttp.onreadystatechange=function() { if (this.readyState==4 && this.status==200) { document.getElementById("rssOutput").innerHTML=this.responseText; } } xmlhttp.open("GET","getrss.php?q="+str,true); xmlhttp.send(); } </script> </head> <body> <form> <select onchange="showRSS(this.value)"> <option value="">Select an RSS-feed:</option> <option value="Google">Google News</option> <option value="ZDN">ZDNet News</option> <option value="job">Job</option> </select> </form> <br> <div id="rssOutput">RSS-feed will be listed here...</div> </body> </html> **后端文件** <?php //get the q parameter from URL $q=$_GET["q"]; //find out which feed was selected if($q=="Google") { $xml=("http://news.google.com/news?ned=us&topic=h&output=rss"); } elseif($q=="ZDN") { $xml=("https://www.zdnet.com/news/rss.xml"); }elseif($q == "job"){ $xml=("https://ngcareers.com/feed"); } $xmlDoc = new DOMDocument(); $xmlDoc->load($xml); //get elements from "<channel>" $channel=$xmlDoc->getElementsByTagName('channel')->item(0); $channel_title = $channel->getElementsByTagName('title') ->item(0)->childNodes->item(0)->nodeValue; $channel_link = $channel->getElementsByTagName('link') ->item(0)->childNodes->item(0)->nodeValue; $channel_desc = $channel->getElementsByTagName('description') ->item(0)->childNodes->item(0)->nodeValue; //output elements from "<channel>" echo("<p><a href='" . $channel_link . "'>" . $channel_title . "</a>"); echo("<br>"); echo($channel_desc . "</p>"); //get and output "<item>" elements $x=$xmlDoc->getElementsByTagName('item'); $count = $x->length; // print_r( $x->item(0)->getElementsByTagName('title')->item(0)->nodeValue); // print_r( $x->item(0)->getElementsByTagName('link')->item(0)->nodeValue); // print_r( $x->item(0)->getElementsByTagName('description')->item(0)->nodeValue); // return; for ($i=0; $i <= $count; $i++) { //Title $item_title = $x->item(0)->getElementsByTagName('title')->item(0)->nodeValue; //Link $item_link = $x->item(0)->getElementsByTagName('link')->item(0)->nodeValue; //Description $item_desc = $x->item(0)->getElementsByTagName('description')->item(0)->nodeValue; //Category $item_cat = $x->item(0)->getElementsByTagName('category')->item(0)->nodeValue; echo ("<p>Title: <a href='" . $item_link . "'>" . $item_title . "</a>"); echo ("<br>"); echo ("Desc: ".$item_desc); echo ("<br>"); echo ("Category: ".$item_cat . "</p>"); } ?>

回答 8 投票 0

PHP 访问 SimpleXMLElement 中包含的数组

代码如下 以下代码 <?php $ans=<<<XML <?xml version="1.0" encoding="utf-8"?> <ResponseDoc xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <response> <index>1</index> <statusCode>Success</statusCode> </response> <response> <index>2</index> <statusCode>Success</statusCode> </response> <response> <index>3</index> <statusCode>Success</statusCode> </response> <response> <index>4</index> <statusCode>Success</statusCode> </response> </ResponseDoc> XML; $r1= simplexml_load_string($ans); print_r($r1); echo '<br>---------------------------------<br>'; $r2=$r1->response; print_r($r2); echo '<br>---------------------------------<br>'; ?> 给出以下输出 SimpleXMLElement Object ( [response] => Array ( [0] => SimpleXMLElement Object ( [index] => 1 [statusCode] => Success ) [1] => SimpleXMLElement Object ( [index] => 2 [statusCode] => Success ) [2] => SimpleXMLElement Object ( [index] => 3 [statusCode] => Success ) [3] => SimpleXMLElement Object ( [index] => 4 [statusCode] => Success ) ) ) --------------------------------- SimpleXMLElement Object ( [index] => 1 [statusCode] => Success ) --------------------------------- 我无法理解为什么,因为在我当前的心理模型中,$r2应该包含一个数组,而不是索引0处的数组的值。 如果我循环 foreach($r1 as $i) echo "statusCode='{$i->statusCode}'<br>"; foreach($r1->response as $i) echo "statusCode='{$i->statusCode}'<br>"; 两种情况下的输出(我不明白为什么它在第一种情况下有效)是: statusCode='Success' statusCode='Success' statusCode='Success' statusCode='Success' 可能我遗漏了对象和数组之间的一些区别,或者存在一些有关 SimpleXMLElement 或 print_r 和 var_dump 工作不正确的特殊细节。 输出是正确的,因为简单的 xml 解析器会自动为您提供第一个对象。但您可以通过使用 xpath 方法来克服这个问题。您还可以使用 print_r($responses) 查看 SimpleXMLElement 中每个项目的数组。 演示:https://3v4l.org/BXhC2 $r1 = simplexml_load_string($ans); $responses = $r1->xpath('//response'); foreach ($responses as $item) { echo $item->index, PHP_EOL; echo $item->statusCode, PHP_EOL; } 1 Success 2 Success 3 Success 4 Success

回答 1 投票 0

XML 子元素未添加,但不会引发任何错误

跟进我之前的问题。 我正在使用 addChild() 添加另一个 元素作为根元素的子元素。我使用了这个问题的代码: $file = "comments.xml"; $

回答 2 投票 0

© www.soinside.com 2019 - 2024. All rights reserved.