So what I would like to do is get the same effect on the xml files. I own a yaml file:
example_route:
enabled: true
policy: 'time_backoff'
reset: '24 hours'
limits:
- limit: 10
interval: '10 seconds'
- limit: 30
interval: '180 seconds'
and I can parse it using the parse function. This will convert it into an array.
Yaml::parseFile(__DIR__ . '/../Resources/config/rate_limiter.yaml');
So now I have programmed an identical xml file:
<?xml version="1.0" encoding="UTF-8" ?>
<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:framework="http://symfony.com/schema/dic/symfony"
xsi:schemaLocation="http://symfony.com/schema/dic/services
https://symfony.com/schema/dic/services/services-1.0.xsd
http://symfony.com/schema/dic/symfony
https://symfony.com/schema/dic/symfony/symfony-1.0.xsd">
<framework:config>
<framework:rate-limiter>
<framework:limiter name="example_route"
policy="time_backoff"
enabled="true"
reset="24 hours">
<limits>
<limit limit="10" interval="10 seconds"/>
<limit limit="30" interval="180 seconds"/>
</limits>
</framework:limiter>
</framework:rate-limiter>
</framework:config>
</container>
and how do I turn this into the same result as the parse function in yaml?
Related
I have sudo string in a sort of xml format which i want to convert to xml in php. Which I then want to grab the imaware which contains date string in different formats and convert to appropriate date.
sudo string
<IMAware>
09-03-2016 05:28
</IMAware>
<NextUpdate>
</NextUpdate>
<ETR>
</ETR>
<SMS>
text
</SMS>
<Summary>
text
</Summary>
<Impact>
text
</Impact>
<Plan>
</Plan>
<Resolution>
text
</Resolution>
<Complete>
text
</Complete>
<Timeline>
text
</Timeline>
<Crisis>
</Crisis>
So far I have the following
for ($i = 0; $i < count($dbData); $i++) {
try {
print_r(trim($dbData[$i]['INCIDENT_NOTES']));
$xml = simplexml_load_string (trim($dbData[$i]['INCIDENT_NOTES']));
print_r($xml);
} catch (Exception $e) {
echo $e;
}
/*$items = $xml->xpath(item);
foreach($items as $item) {
echo $item['title'], ': ', $item['description'], "\n";
}*/
}
This fails with
Warning: simplexml_load_string(): Entity: line 5: parser error : Extra content at the end of the document in /var/SP/oiadm/docroot/dev/maskella/common/api/Api.class.php on line 1444
Do I need to enclose with<?xml version='1.0'?> <document></document>?
Date formats which I have are
21-02-2016 20:14
Date/Time: 09/02 - 15:40
Date: 08/02 - 11:50
Yes, the xml doc will need the header, and will also need a root element which encapsulates the elements from your sudo example.
See What is the correct format to use for Date/Time in an XML file for appropriate date formats in XML.
Below is my xml with namespace
<?xml version="1.0" encoding="UTF-8"?>
<hotels xmlns="http://www.test.com/schemas/messages" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" schemaLocation="http://www.test.com/schemas/messages">
<hotel >
<rooms>
<room>
<rates>
<rate id="1" adults="1" child="0"></rate>
<rate id="2" adults="2" child="0"></rate>
<rate id="3" adults="1" child="0"></rate>
</rates>
</room>
<room>
<rates>
<rate id="4" adults="1" child="0"></rate>
<rate id="5" adults="2" child="0"></rate>
<rate id="6" adults="2" child="0"></rate>
</rates>
</room>
</rooms>
</hotel>
</hotels>
i trying below php code (xpath) using foreach to get values of the ratenode
$xd = simplexml_load_file('C:/inetpub/vhosts/test.com/data_download/q.xml');
$xd->registerXPathNamespace("n", "http://www.test.com/schemas/messages");
foreach($xd->xpath("//n:hotels/n:hotel") as $xd_item)
{
echo 'item - A';
foreach($xd_item->xpath("rooms/room") as $xd_room)
{
foreach($xd_room->xpath("rates/rate") as $xd_rate)
{
echo 'rate - C';
}
}
}
In the foreach of $xd_item is not working. I mean the 2nd foreach its end with the value "echo 'item - A';" anyone can help me?
The problem with your codes is, as mentioned by #kjhughes in his comment, that some elements are in the default namespace but your XPath missed to use the corresponding prefix on those elements. Also, your code prints static literal strings i.e 'item - A' and 'rate - C', not any part of the XML being parsed.
" Is possible to write conditions like $xd->xpath("rates/rate[#id='1']") in dom"
Yes it is possible. It is also possible using SimpleXML, for example :
$xd->registerXPathNamespace("n", "http://www.test.com/schemas/messages");
foreach($xd->xpath("//n:rate[#id='1']") as $rate){
echo $rate["id"] .", ". $rate["adults"] .", ". $rate["child"] ."\r\n";
}
eval.in demo
output :
//id, adults, rate
1, 1, 0
The variable $xd_item is of type SimpleXMLElement from which you can access its room properties like this for example:
$xd_item->rooms->room
This will return an object of type SimpleXMLElement from which you can get the rates and you can loop using a foreach. The values that you want from the 'rate' are in the attributes
For example:
$xd = simplexml_load_file('C:/inetpub/vhosts/test.com/data_download/q.xml');
$xd->registerXPathNamespace("n", "http://www.test.com/schemas/messages");
foreach($xd->xpath("//n:hotels/n:hotel") as $xd_item)
{
foreach($xd_item->rooms->room as $room) {
foreach ($room->rates->rate as $rate) {
echo sprintf(
'id: %s<br>adults: %s<br>child: %s<br><br>',
$rate->attributes()->id->__toString(),
$rate->attributes()->adults->__toString(),
$rate->attributes()->child->__toString()
);
}
}
}
Whether the 25 digits are decimal and integers or just integers, DOMDocument::schemaValidate() fires a warning, return false, and libxml_get_errors(); captures the next errors:
PHP snippet:
$DD = new DOMDocument('1.0', 'ISO-8859-1');
$DD -> loadXML('<?xml version ="1.0" encoding="ISO-8859-1"?><a></a>');
libxml_use_internal_errors(true);
$old_libxml_disable_entity_loader = libxml_disable_entity_loader(false);
$DD -> schemaValidate(__DIR__ . '/schemas/schema.xsd'); // WARNING
libxml_disable_entity_loader($old_libxml_disable_entity_loader);
$errors = libxml_get_errors();
foreach ($errors as $error) { // PRINT ERRORS
echo $error -> code . '<br>';
echo $error -> message . '<br>';
}
DOMDocument::schemaValidate() Generated Errors:
Error 1824:
Element '{http://www.w3.org/2001/XMLSchema}maxInclusive':
'9999999999999999999999999' is not a valid value of the
atomic type 'xs:decimal'. in /path/schema.xsd on line X
Error 1717:
Element '{http://www.w3.org/2001/XMLSchema}maxInclusive': The value
'9999999999999999999999999' of the facet does not validate
against the base type '{http://www.w3.org/2001/XMLSchema}decimal'. in
/path/schema.xsd on line X
Valid schema (invalid XML only):
<?xml version="1.0" encoding="ISO-8859-1"?>
<xs:schema
targetNamespace="http://www.lala.com/la"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:la="http://www.lala.com/la"
elementFormDefault="qualified"
attributeFormDefault="unqualified">
<xs:simpleType name="AmountType">
<xs:restriction base="xs:decimal">
<xs:totalDigits value="100"/>
<xs:fractionDigits value="20"/>
<xs:maxInclusive value="999999999999999999999999"/><!-- 24 DIGITS -->
</xs:restriction>
</xs:simpleType>
</xs:schema>
Invalid schema: WARNING + Libxml internal errors of invalid schema
<?xml version="1.0" encoding="ISO-8859-1"?>
<xs:schema
targetNamespace="http://www.lala.com/la"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:la="http://www.lala.com/la"
elementFormDefault="qualified"
attributeFormDefault="unqualified">
<xs:simpleType name="AmountType">
<xs:restriction base="xs:decimal">
<xs:totalDigits value="100"/>
<xs:fractionDigits value="20"/>
<xs:maxInclusive value="9999999999999999999999999"/><!-- 25 DIGITS -->
</xs:restriction>
</xs:simpleType>
</xs:schema>
PHP version: 5.5.20
Libxml version: 2.9.2
According to W3C XML Schema Part 2: Datatypes Second Edition, libxml2 can limit the range of maxInclusive because it is allowed to limit the range of the value space of xs:decimal...
4.3.7 maxInclusive:
[Definition:] maxInclusive is the ·inclusive upper bound· of the
·value space· for a datatype with the ·ordered· property. The value of
maxInclusive ·must· be in the ·value space· of the ·base type·.
3.2.3 decimal
Note: All ·minimally conforming· processors ·must· support decimal
numbers with a minimum of 18 decimal digits (i.e., with a
·totalDigits· of 18). However, ·minimally conforming· processors ·may·
set an application-defined limit on the maximum number of decimal
digits they are prepared to support, in which case that
application-defined maximum number ·must· be clearly documented.
This is what I currently have for my PHP file:
<?php header("Content-type: text/xml"); ?>
<?php echo "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"; ?>
<rss version="2.0">
<channel>
<title>My Website</title>
<link>http://www.mywebsite.com</link>
<description>The Title of My Website</description>
<pubDate>Tue, 15 Apr 2008 18:00:00 +0000</pubDate>
<item>
<title>Website Directory - Page NUMBER</title>
<pubDate><?echo date('Y/m/d H:i:s');?></pubDate>
<link>http://www.mywebsite.com/directory/NUMBER</link>
<description>New update to page NUMBER in the Website Directory.</description>
</item>
</channel>
</rss>
That right there is correctly showing one entry in the RSS feed. However, I need it to show 30 entries, each with a random number entered in the three places where NUMBER is shown in the item.
Each RSS item should have a different number between 1 and 2779503 entered in the three places that say NUMBER. I know that PHP has http://php.net/manual/en/function.rand.php but what I don't know how to do is have it loop through 30 random numbers each time the feed is loaded...
<?php
foreach( range( 1, 30 ) as $i ):
$number = mt_rand( 1, 2779503 );
?>
<item>
<title>Website Directory - Page <?php echo $number; ?></title>
<pubDate><?echo date('Y/m/d H:i:s');?></pubDate>
<link>http://www.mywebsite.com/directory/<?php echo $number; ?></link>
<description>New update to page <?php echo $number; ?> in the Website Directory.</description>
</item>
<?php endforeach; ?>
I want to load XML file and then remove all <Charge> where <DispositionDate> is bigger/older then 7 years. Date format is YYYY-MM-DD.
XML example:
<BackgroundReports userId="" password="" account="" >
<BackgroundReportPackage>
<Screenings>
<Screening type="criminal" qualifier="">
<CriminalReport>
<CriminalCase>
<AgencyReference type="Docket">
<IdValue>CR-0870120-09</IdValue>
</AgencyReference>
<Charge>
<ChargeId>
<IdValue>1</IdValue>
</ChargeId>
<ChargeOrComplaint>DUI: HIGHEST RTE OF ALC (BAC .16+) 1ST OFF</ChargeOrComplaint>
<ChargeTypeClassification>unknown</ChargeTypeClassification>
<DispositionDate>2009-04-07</DispositionDate>
</Charge>
<Charge>
<ChargeId>
<IdValue>2</IdValue>
</ChargeId>
<ChargeOrComplaint>CARELESS DRIVING</ChargeOrComplaint>
<ChargeTypeClassification>unknown</ChargeTypeClassification>
<DispositionDate>2010-08-02</DispositionDate>
</Charge>
<Charge>
<ChargeId>
<IdValue>3</IdValue>
</ChargeId>
<ChargeOrComplaint>STATUTE: 475 PC</ChargeOrComplaint>
<ChargeTypeClassification>misdemeanor</ChargeTypeClassification>
<OffenseDate>1988-11-05</OffenseDate>
<Disposition>CONVICTED</Disposition>
<DispositionDate>1988-11-09</DispositionDate>
<DispositionDate>1988-11-05</DispositionDate>
<DispositionDate>1988-11-09</DispositionDate>
</Charge>
</CriminalCase>
</CriminalReport>
</Screening>
</Screenings>
</BackgroundReportPackage>
</BackgroundReports>
I know how to open and close/save file using PHP, I don't know how to delete the part i don't want... If anyone would help me with that I would be extremly thankfull!
You can either use SimpleXML, DOM or XSL for it.
Example XML (shortened for brevity (from Revision 1 of your question)):
$xml = <<< XML
<CriminalCase>
<Charge>
<DispositionDate>1995-12-21</DispositionDate>
</Charge>
<Charge>
<DispositionDate>2010-12-21</DispositionDate>
</Charge>
</CriminalCase>
XML;
With SimpleXml
$sevenYearsAgo = new DateTime('-7 years');
$CriminalCase = new SimpleXmlElement($xml);
for ($i = 0; $i < $CriminalCase->Charge->count(); $i++) {
$dispositionDate = new DateTime($CriminalCase->Charge->DispositionDate);
if ($dispositionDate < $sevenYearsAgo) {
unset($CriminalCase->Charge[$i]);
}
}
echo $CriminalCase->asXml();
With DOM
$dom = new DOMDocument;
$dom->loadXml($xml);
$xpath = new DOMXPath($dom);
$oldCases = $xpath->query(
sprintf(
'//Charge[substring-before(DispositionDate, "-") < %d]',
date('Y', strtotime('-7 years'))
)
);
foreach ($oldCases as $oldCase) {
$oldCase->parentNode->removeChild($oldCase);
}
echo $dom->saveXml();
With XSLT
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:date="http://exslt.org/dates-and-times"
extension-element-prefixes="date">
<xsl:output indent="yes" method="xml"/>
<xsl:template match="/">
<CriminalCase>
<xsl:apply-templates />
</CriminalCase>
</xsl:template>
<xsl:template match="Charge">
<xsl:if test="date:year(DispositionDate) > date:year() - 7">
<xsl:copy-of select="."/>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
and then use this PHP Code to transform it
$doc = new DOMDocument();
$xsl = new XSLTProcessor();
$doc->loadXml($xsl);
$xsl->importStyleSheet($doc);
$doc->loadXml($xml);
echo $xsl->transformToXML($doc);
Here are some tips on how to get started:
You need to parse the XML to something a little easier to work with. PHP has a library called SimpleXML.
Loop through the data and remove the objects which are older than 7 years. To compare dates you have to first convert the dates you got from the XML to something PHP can process as a date. Take a look at strtotime which gives you the timestamp (seconds since 1970, actually 1901 for version > 5.1.0) or DateTime which supports dates before 1970.
To check if the fetched date is older than 7 years ago, you need to (one way) subtract the timestamp with the current timestamp, and see if that value is greater than 7 years in seconds. Or if you use DateTime, you can take a look at DateTime::diff. Remove the objects that you iterate over that are older than 7 years (unset).
To save as XML again, take a look at SimpleXMLElement::asXML
Hope that helps!