How can I find an xml string using php in this case? - php

I want my php-script to download files from a specific link based on xml id's. I want it to ignore the rest of the xml-code, I want it to just look at the first id of every lib.
My xml looks like this:
**
<lib id="ITEM_I_WANT_TO_DOWNLOAD_1" revision="0000">
<part id="0000" type="ch"/>
<part id="0000" type="ls"/>
<part id="0000" type="rs"/>
<part id="0000" type="ch"/>
</lib>
<lib id="ITEM_I_WANT_TO_DOWNLOAD_2" revision="0000">
<part id="0000" type="ch"/>
<part id="0000" type="ls"/>
<part id="0000" type="rs"/>
<part id="0000" type="ch"/>
</lib>
**
My current PHP-script looks like this:
if (!defined('STDIN'))
{
echo 'Please run it as a cmd ({path to your php}/php.exe {path to badges.php} -f)';
exit;
}
define('BASE', 'https://randomtarget.com/');
$figuremap = get_remote_data('https://random/xmlfile-needed.xml/');
if (!file_exists('C:/outputfolder/')) {
mkdir('C:/outputfolder/', 0777, true);
echo "\n --------------> Output folder has been made... \n";
sleep(3);
$fp = fopen("C:/downloaded-xmlfile.xml", "w");
fwrite($fp, $figuremap);
fclose($fp);
echo "\n --------------> XML downloaded and placed into folder \n";
sleep(3);
}
$pos = 0;
while ($pos = strpos($figuremap, '<lib id="', $pos +1))
{
$pos1 = strpos($figuremap, '"', $pos);
$rule = substr($figuremap, $pos, ($pos1 -$pos));
$rule = explode(',', $rule);
$revision = str_replace('">', '', $rule[1]);
$clothing_file = current(explode('*', str_replace('"', '', $rule[2])));
if (file_exists('C:/outputfolder/'.$clothing_file.'.swf'))
{
echo 'Clothing_file found: '.$clothing_file."\r\n";
continue;
}
echo 'Download clothing_file: '.$clothing_file.' '.$revision."\r\n";
if (!#copy(BASE.'/'.$revision.'/'.$clothing_file.'.swf', 'C:/outputfolder'.$clothing_file.'.swf'))
{
echo 'Error downloading: '.$clothing_file."\r\n";
}
}
Beside this code I wrote a get_remote_data function so that's allright. I just want the strpos to grab all the id='' items to check if the files exist on the target-site.
How can I fix it?

There are some easy ways of processing XML files, the easiest (but less flexible) is SimpleXML, the following code should replace the main processing loop...
$xml = simplexml_load_string($figuremap);
foreach ( $xml->lib as $lib ) {
$clothing_file = (string) $lib['id'];
if (file_exists('C:/outputfolder/'.$clothing_file.'.swf'))
{
echo 'Clothing_file found: '.$clothing_file."\r\n";
continue;
}
echo 'Download clothing_file: '.$clothing_file.' '.$revision."\r\n";
if (!#copy(BASE.'/'.$revision.'/'.$clothing_file.'.swf', 'C:/outputfolder'.$clothing_file.'.swf'))
{
echo 'Error downloading: '.$clothing_file."\r\n";
}
}
The start point is to load the XML you have in $figuremap into SimpleXML, then to loop over the elements. This assumes an XML structure of something like...
<lib1>
<lib id="ITEM_I_WANT_TO_DOWNLOAD_1" revision="0000">
<part id="0000a" type="ch" />
<part id="0000" type="ls" />
<part id="0000" type="rs" />
<part id="0000" type="ch" />
</lib>
<lib id="ITEM_I_WANT_TO_DOWNLOAD_2" revision="0000">
<part id="00001" type="ch" />
<part id="0000" type="ls" />
<part id="0000" type="rs" />
<part id="0000" type="ch" />
</lib>
</lib1>
The actual name of the base element doesn't matter as long as the <lib> elements are 1 level down then you can use $xml->lib to loop over them.

Your posted xml string is actually invalid. It needs to be wrapped in a parent element to be repaired. I'm not sure if you are posting your exact xml string or just a section of it.
$xml = '<lib id="ITEM_I_WANT_TO_DOWNLOAD_1" revision="0000">
<part id="0000" type="ch"/>
<part id="0000" type="ls"/>
<part id="0000" type="rs"/>
<part id="0000" type="ch"/>
</lib>
<lib id="ITEM_I_WANT_TO_DOWNLOAD_2" revision="0000">
<part id="0000" type="ch"/>
<part id="0000" type="ls"/>
<part id="0000" type="rs"/>
<part id="0000" type="ch"/>
</lib>';
$xml = '<mydocument>' . $xml . '</mydocument>'; // repair invalid xml
https://stackoverflow.com/q/4544272/2943403
$doc = new DOMDocument();
$doc->loadXml($xml);
$xpath = new DOMXpath($doc);
foreach ($xpath->evaluate('//lib/#id') as $attr) {
$clothing_file = $attr->value;
// perform your conditional actions ...
}
//lib/#id says search for the id attribute of all <lib> elements, anywhere in the document.

Related

Get value of child from the value of another child with the same parent in XML using PHP

I have the following XML document:
<response>
<message>
<badgeid>13</badgeid>
<level>4672</level>
<completion_time>1518626787</completion_time>
<xp>4922</xp>
<scarcity>9717</scarcity>
</message>
<message>
<badgeid>25</badgeid>
<level>1</level>
<completion_time>1480166791</completion_time>
<xp>25</xp>
<scarcity>3761041</scarcity>
</message>
<message>
<badgeid>21</badgeid>
<level>1</level>
<completion_time>1467581153</completion_time>
<xp>100</xp>
<scarcity>16650345</scarcity>
</message>
</response>
I am trying to create a program using PHP that returns the "scarcity" of a certain "badgeid" (that is always unique).
So my question is: How do I get the value of <scarcity></scarcity> when the only input I receive from the user is a unique badgeid? In general words: How do I get the value of a child from the value of another child with the same parent?
You could also use an xpath expression and use the $badgeid as a parameter:
$expression = "/response/message[./badgeid='$badgeid']";
Then you could for example use SimpleXMLElement or DOMDocument.
$data = <<<DATA
<response>
<message>
<badgeid>13</badgeid>
<level>4672</level>
<completion_time>1518626787</completion_time>
<xp>4922</xp>
<scarcity>9717</scarcity>
</message>
<message>
<badgeid>25</badgeid>
<level>1</level>
<completion_time>1480166791</completion_time>
<xp>25</xp>
<scarcity>3761041</scarcity>
</message>
<message>
<badgeid>21</badgeid>
<level>1</level>
<completion_time>1467581153</completion_time>
<xp>100</xp>
<scarcity>16650345</scarcity>
</message>
</response>
DATA;
$badgeid = 25;
$xml = simplexml_load_string($data);
$expression = "/response/message[./badgeid='$badgeid']";
$items = $xml->xpath($expression);
if (count($items) === 1) {
echo $items[0]->scarcity;
}
$doc = new DOMDocument();
$doc->loadXML($data);
$xpath = new DOMXpath($doc);
$res = $xpath->query($expression);
if ($res->length === 1) {
echo $res->item(0)->getElementsByTagName("scarcity")->item(0)->nodeValue;
}
Demo
You could use simplexml_load_string() for an XML string, or simplexml_load_file() if it is a XML file. Then you could iterate over $xml->message and check if $message->badgeid is the item you want :
$xmlstr = '<response>
<message>
<badgeid>13</badgeid>
<level>4672</level>
<completion_time>1518626787</completion_time>
<xp>4922</xp>
<scarcity>9717</scarcity>
</message>
<message>
<badgeid>25</badgeid>
<level>1</level>
<completion_time>1480166791</completion_time>
<xp>25</xp>
<scarcity>3761041</scarcity>
</message>
<message>
<badgeid>21</badgeid>
<level>1</level>
<completion_time>1467581153</completion_time>
<xp>100</xp>
<scarcity>16650345</scarcity>
</message>
</response>';
$badgeid = 21 ; // The value you want to search
$xml = simplexml_load_string($xmlstr);
$scarcity = null ;
foreach ($xml->message as $message) {
if ((string)$message->badgeid == $badgeid) {
$scarcity = (string)$message->scarcity ;
break ;
}
}
// use $scarcity if set.
if (isset($scarcity)) {
// do stuff
echo $scarcity ; // 16650345
}

Nusoap error "no operations defined in the WSDL document!"

Hi I'm getting an error:
no operations defined in the WSDL document!
I'm searching all possible ways that might answer my problem for almost a week but no luck I can't find it. I use nusoap library and here's my code:
<?php
include_once('lib/nusoap.php');
$username = 'xxxxx#username.com';
$password = 'xxxxxxx';
$endpoint = 'https://mail.xxxxxxxxx.com/ews/services.wsdl';
$wsdl = true;
$soapclient = new nusoap_client($endpoint, $wsdl);
$xml = '<wsdl:definitions targetNamespace="http://schemas.microsoft.com/exchange/services/2006/messages">';
$xml .= '<wsdl:message name="UploadItemsSoapIn">';
$xml .= '<wsdl:part name="request" element="tns:UploadItems"/>';
$xml .= '<wsdl:part name="Impersonation" element="t:ExchangeImpersonation"/>';
$xml .= '<wsdl:part name="MailboxCulture" element="t:MailboxCulture"/>';
$xml .= '<wsdl:part name="RequestVersion" element="t:RequestServerVersion"/>';
$xml .= '</wsdl:message>';
$xml .= '</wsdl:definitions>';
$operation = 'UploadItemsSoapIn';
$result = $soapclient->call($operation,$xml);
$soapclient->setCredentials($username, $password, 'ntlm');
if ($soapclient->fault) {
echo '<h2>Fault (Expect - The request contains an invalid SOAP body)</h2><pre>'; print_r($result); echo '</pre>';
} else {
$err = $soapclient->getError();
if ($err) {
echo '<h2>Error</h2><pre>' . $err . '</pre>';
} else {
echo '<h2>Result</h2><pre>'; print_r($result); echo '</pre>';
}
}
and this is the view in services.wsdl link:
<wsdl:definitions targetNamespace="http://schemas.microsoft.com/exchange/services/2006/messages">
<wsdl:types>
<xs:schema>
<xs:import namespace="http://schemas.microsoft.com/exchange/services/2006/messages" schemaLocation="messages.xsd"/>
</xs:schema>
</wsdl:types>
<wsdl:message name="UploadItemsSoapIn">
<wsdl:part name="request" element="tns:UploadItems"/>
<wsdl:part name="Impersonation" element="t:ExchangeImpersonation"/>
<wsdl:part name="MailboxCulture" element="t:MailboxCulture"/>
<wsdl:part name="RequestVersion" element="t:RequestServerVersion"/>
</wsdl:message>
<wsdl:message name="UploadItemsSoapOut">
<wsdl:part name="UploadItemsResult" element="tns:UploadItemsResponse"/>
<wsdl:part name="ServerVersion" element="t:ServerVersionInfo"/>
</wsdl:message>
Sorry I'm just a newbie in soap. All I want is just to run the basic function and just display email or names of the login user. Thanks in advance!

PHP - Wrong date format

I am trying to communicate with a SOAP server and I am sending data to server however it is rejecting the date format that I am using. I have literally tried everything for the last two days and as far as I am seeing the format is correct. This is the code I am using to generate the date. I have read over similar questions but I cant seem to find an answer in any of them.
$_dateTo=date('Y-m-d');
Output
2015-01-28
This is the error that it generates.
SoapFault Object ( [message:protected] => Date to is in wrong format, should be: 'YYYY-MM-DD' [string:Exception:private]
This is the XML
<message name="webrequestRequest">
<part name="studentId" type="xsd:integer"/>
<part name="type" type="xsd:string"/>
<part name="dateFrom" type="xsd:date"/>
<part name="dateTo" type="xsd:date"/>
<part name="description" type="xsd:string"/>
<part name="extraField1" type="xsd:string"/>
<part name="extraField2" type="xsd:string"/>
<part name="extraField3" type="xsd:string"/>
</message>
Try the following and see if it gives you any errors
$dateFrom = new DateTime();
$dateTo = new DateTime();
$writer = new XMLWriter();
$writer->openMemory();
$writer->startDocument('1.0', 'UTF-8');
$writer->startElement('message');
$writer->startElement('part');
$writer->writeAttribute('name', 'studentId');
$writer->writeAttribute('type', 'xsd:integer');
$writer->Text();
$writer->endElement($studentId);
$writer->startElement('part');
$writer->writeAttribute('name', 'type');
$writer->writeAttribute('type', 'xsd:string');
$writer->Text($type);
$writer->endElement();
$writer->startElement('part');
$writer->writeAttribute('name', 'dateFrom');
$writer->writeAttribute('type', 'xsd:date');
$writer->Text($dateFrom->format('Y-m-d'));
$writer->endElement();
$writer->startElement('part');
$writer->writeAttribute('name', 'dateTo');
$writer->writeAttribute('type', 'xsd:date');
$writer->Text($dateTo->format('Y-m-d'));
$writer->endElement();
$writer->startElement('part');
$writer->writeAttribute('name', 'description');
$writer->writeAttribute('type', 'xsd:string');
$writer->Text($description);
$writer->endElement();
$writer->startElement('part');
$writer->writeAttribute('name', 'extraField1');
$writer->writeAttribute('type', 'xsd:string');
$writer->Text($extraField1);
$writer->endElement();
$writer->startElement('part');
$writer->writeAttribute('name', 'extraField2');
$writer->writeAttribute('type', 'xsd:string');
$writer->Text($extraField2);
$writer->endElement();
$writer->startElement('part');
$writer->writeAttribute('name', 'extraField3');
$writer->writeAttribute('type', 'xsd:string');
$writer->Text($extraField3);
$writer->endElement();
$writer->endElement(); // /message
$writer->endDocument();
$message = $writer->outputMemory(true);
Don't forget to set your values first.

validate a xml file against a xsd using php

how to validate a xml file against a xsd? there is domdocument::schemaValidate() but It does not tell where are the errors. is there any class for that? does it have any worth making that parser from scratch? or is it just reinventing he wheel,
This code does the business:
$xml= new DOMDocument();
$xml->loadXML(<A string goes here containing the XML data>, LIBXML_NOBLANKS); // Or load if filename required
if (!$xml->schemaValidate(<file name for the XSD file>)) // Or schemaValidateSource if string used.
{
// You have an error in the XML file
}
See the code in http://php.net/manual/en/domdocument.schemavalidate.php To retrieve the errors.
I.e.
justin at redwiredesign dot com 08-Nov-2006 03:32 post.
User contrib from http://php.net/manual/en/domdocument.schemavalidate.php
It works like a charm!
For more detailed feedback from DOMDocument::schemaValidate, disable
libxml errors and fetch error information yourself. See
http://php.net/manual/en/ref.libxml.php for more info.
example.xml
<?xml version="1.0"?>
<example>
<child_string>This is an example.</child_string>
<child_integer>Error condition.</child_integer>
</example>
example.xsd
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified">
<xs:element name="example">
<xs:complexType>
<xs:sequence>
<xs:element name="child_string" type="xs:string"/>
<xs:element name="child_integer" type="xs:integer"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
PHP
<?php
function libxml_display_error($error)
{
$return = "<br/>\n";
switch ($error->level) {
case LIBXML_ERR_WARNING:
$return .= "<b>Warning $error->code</b>: ";
break;
case LIBXML_ERR_ERROR:
$return .= "<b>Error $error->code</b>: ";
break;
case LIBXML_ERR_FATAL:
$return .= "<b>Fatal Error $error->code</b>: ";
break;
}
$return .= trim($error->message);
if ($error->file) {
$return .= " in <b>$error->file</b>";
}
$return .= " on line <b>$error->line</b>\n";
return $return;
}
function libxml_display_errors() {
$errors = libxml_get_errors();
foreach ($errors as $error) {
print libxml_display_error($error);
}
libxml_clear_errors();
}
// Enable user error handling
libxml_use_internal_errors(true);
$xml = new DOMDocument();
$xml->load('example.xml');
if (!$xml->schemaValidate('example.xsd')) {
print '<b>DOMDocument::schemaValidate() Generated Errors!</b>';
libxml_display_errors();
}
?>
This is a complete code snippet for displaying xsd validation errors:
$xml = '<test/>';
$xsd = '/path/to/xsd';
// needed for getting errors
libxml_use_internal_errors(true);
$domDocument= new DOMDocument();
$domDocument->loadXML($xml);
if (!$domDocument->schemaValidate($xsd)) {
$errors = libxml_get_errors();
foreach ($errors as $error) {
print_r($error);
}
libxml_clear_errors();
}

read XML tag id from php

i am have the following XML file
<?xml version="1.0" encoding="iso-8859-1"?>
<Message Id="Language">German</Message>
<Message Id="LangEnglish">German</Message>
<Message Id="TopMakeHomepage">
Mache 4W Consulting Webseite zu deiner Starseite!
</Message>
<Message Id="TopLinkEmpSec">
4W Mitarbeiter
</Message>
<Message Id="TopLinkFeedback">
Feedback
</Message>
<Message Id="TopLinkSiteMap">
Site Map
</Message>
<Message Id="TopLinkContactUs">
Kontakt
</Message>
<Message Id="TopSetLangEn">
ins Englische
</Message>
<Message Id="TopSetLangDe">
ins Deutsche
</Message>
<Message Id="TopSetLangEs">
ins Spanische
</Message>
<Message Id="MenuLinks">
!~|4W Starseite|Company|Über uns|Kontakt|4W anschließen|Services|Kunden Software Entwicklung|Altsystem Neugestalltung & Umwandlung|Altsystem Dokumentation|Daten Umwandlung & Migration|Erstellen von Datenbeschreibungsverzeichnis|System- & Anwendungs Support|Projekt Management & Planunng|Personal Erweiterung|Projekt Ausgliederung|Mitarbeiter Ausbildung|Technologie|Intersystems Caché|M / MUMPS|Zusätzliche Technologien|Methodologie|Feedback|~!
</Message>
</MsgFile>
in this XML file i need to fetch the contents using the tagid . what exactly i need is when i input the 'TopMakeHomepage' i need output as 'Mache 4W Consulting Webseite zu deiner Starseite!' ...
Please help me to find out this . Thanks in advance
Use SimpleXML:
$xml = simplexml_load_file($grabUrl);
foreach ($xml->Message as $message) {
echo $message->attributes()->Id.'<br />';
}
Or use XMLReader, with which you can miss memory leaks when processing large XMLs.
$xml = new XMLReader;
$xml->open($grabUrl);
while ($xml->read()) {
if ($xml->nodeType === XMLReader::ELEMENT && $xml->name == 'Message')
echo $xml->getAttribute('Id');
}
With the DOM extension it should be something like this:
$dom = new DOMDocument;
$dom->validateOnParse = TRUE;
$dom->loadXML($xmlString); // or use ->load('file.xml')
$node = $dom->getElementById('foo');
echo $node->nodeValue;
See the manual on
DOMDocument::getElementById — Searches for an element with a certain id
If it doesn't work with getElementById (which usually only happens if the DTD doesn't know the id attribute), you can still use XPath to do the query:
$xpath = new DOMXPath($dom);
$nodes = $xpath->query('//Message[#id = "foo"]');
foreach($nodes as $node) {
echo $node->nodeValue;
}
Unlike getElementById, an XPath query always returns a DOMNodeList. It will be empty if the query didn't find any nodes.
If the ID is a real XML ID, you can also use the id() function in XPath
$xpath = new DOMXPath($dom);
$nodes = $xpath->query('id("foo")');
foreach($nodes as $node) {
echo $node->nodeValue;
}
See Simplify PHP DOM XML parsing - how? for more details on XML IDs.
For SimpleXML this should do the trick:
$xml = simplexml_load_file($xmlFileLoc);
foreach ($xml->Message as $msg)
{
echo $msg['Id'];
}

Categories