I need som help reading a XML that has namespaces.
I can read file with out any namepaces but not with namespaces..
XML sample:
<?xml version="1.0" encoding="utf-8"?>
<OrderResponse xmlns:cac="urn:basic:names:specification:ubl:schema:xsd:CommonAggregateComponents-2" xmlns:xsi="http://www.w3.org/" xmlns:cbc="urn:basic:names:specification:ubl:schema:xsd:BasicComponents-2" xmlns="urn:basic:names:specification:ubl:schema:xsd:OrderResponse-2">
<cbc:UBLVersionID>2.1</cbc:UBLVersionID>
<cbc:AccountingCostCode>TESTER TEST</cbc:AccountingCostCode>
<cac:OrderReference>
<cbc:ID>100067010</cbc:ID>
<cbc:IssueDate>2016-06-15</cbc:IssueDate>
<cbc:OrderTypeCode>EDI</cbc:OrderTypeCode>
</cac:OrderReference>
</OrderResponse>
I need to get the value of the ..
Im trying do it with DomDocument.
Here is my code:
function SearchXMLID($xml){
var_dump($xml);
$doc = new DOMDocument();
$doc->load($xml);
$id = $doc->getElementsByTagNameNS('urn:basic:names:specification:ubl:schema:xsd:CommonAggregateComponents-2','cbc:ID');
foreach($id as $i){
echo "<pre>";var_dump('NS',$i->nodeValue,PHP_EOL);"</pre>";
}
}
$files = glob('dataXMl/*xml');
echo "<pre>";var_dump($files,PHP_EOL);"</pre>";
foreach($files as $f){
SearchXMLID($f);
}
This code works but is getting all namespaces with 'cbc:' and stores the in a string..
array(1) {
[0]=>
string(17) "dataXMl/test1.xml"
}
string(1) "
"
string(17) "dataXMl/test1.xml"
string(2) "NS"
string(40) "
100000050
2016-06-15
EDI
"
string(1) "
"
It gets all tags with the namespace 'cbc'.. but i want to get the tag 'cbc:ID' only.
What am i doing wrong?
I'm no expert with php coding but my gut tells me that both of your parameters for getElementsByTagNameNS are wrong.
Try this:
$id = $doc->getElementsByTagNameNS('urn:basic:names:specification:ubl:schema:xsd:BasicComponents-2','ID');
i.e. use the correct namespace-uri: "urn:basic:names:specification:ubl:schema:xsd:BasicComponents-2"
and drop the cbc prefix
Related
I'm trying to create database of new releases from boomkat.com RSS feed. Feed is located here:
link
Now, I'm having issues with selection of stuff inside paragraph tags.
One paragraph in RSS feed looks like this:
<p>GOAT<br/>World Music<br/>ROCKET RECORDINGS<br/>INDIE / ROCK / ALTERNATIVE<br/>MP3 Release</p>
What I did so far is this:
<?php
$dom = new DOMDocument;
$dom->validateOnParse = true;
$dom->load("http://feeds.boomkat.com/boomkat_downloads_just_arrived");
$content = $dom->getElementsByTagName('content');
foreach ($content as $result) {
echo $result->nodeValue, PHP_EOL;
}
?>
But that gives me whole feed. Writing 'p' in getElementsByTagName doesn't work.
I would suggest using DOMDocument::loadHTMLFile() method instead of DOMDocument::load() (as load() is strictly for reading XML, not HTML).
The reason why you're getting the whole document, is because you are querying the entire document for a element called "content". There is no such HTML element. Instead you should be using
$dom->getElementsByTagName('p');
This will grab all the tags in the HTML document, and then you can loop over that. The primary reason why querying tags with "p" doesn't work, is because you need to load the document as strict HTML, and not use the default XML.
OK, well I don't understand why you're having problems, but I just tried what I suggested with the URL you provided, and got a proper print out of all the text of each <p> tag.
Here's the code:
$doc = new DOMDocument();
$doc->loadHTMLFile("http://boomkat.com/downloads/601228-goat-world-music");
$content = $doc->getElementsByTagName("p");
foreach($content as $element) {
Util::debug($element->textContent); // helper method similar to PHP's var_dump()
}
Here's the results I was able to print to the screen:
string(91) "Residual Echoes have come up with a really rather lovely disc of psychedelic folk goodness."
string(8) "MAMMATUS"
string(8) "Mammatus"
string(17) "ROCKET RECORDINGS"
string(45) "MP3 Download // £2.95FLAC Download // £3.95"
string(0) ""
string(19) "SERPENTINA SATELITE"
string(16) "Mecanica Celeste"
string(17) "ROCKET RECORDINGS"
string(45) "MP3 Download // £3.95FLAC Download // £4.95"
string(0) ""
string(12) "SUNCOIL SECT"
string(25) "One Note Obscures Another"
string(17) "ROCKET RECORDINGS"
string(45) "MP3 Download // £6.99FLAC Download // £7.99"
string(0) ""
string(16) "TEETH OF THE SEA"
string(10) "Hypnoticon"
string(17) "ROCKET RECORDINGS"
string(45) "MP3 Download // £2.50FLAC Download // £3.50"
string(52) "Proggy kosmiche rock from London's Teeth Of The Sea."
string(16) "TEETH OF THE SEA"
string(21) "Orphaned By the Ocean"
string(17) "ROCKET RECORDINGS"
string(45) "MP3 Download // £5.99FLAC Download // £6.99"
Was this something you were doing in the code?
I have the following XML: http://pastebin.com/QiRK72BK
which is generated in response to a REST query. My code is very simple:
$xml = simplexml_load_file($url);
var_dump($xml->getName());
var_dump($xml->xpath("serverDetail/apiEnv"));
in an attempted test case. The first var_dump reveals that the XML file is indeed being loaded:
string(21) "GeneralSearchResponse"
However, the second var_dump puzzles me. I feel it should definitely match some data, but instead I get
array(0) { }
I've also tried the xpath "/serverDetail/apiEnv" "//apiEnv" and "/" and always get an empty array. Am I misunderstanding xpath or perhaps missing some initialization step?
Your XML is using a namespace:
$xml->registerXPathNamespace('u', 'urn:types.partner.api.shopping.com');
var_dump($xml->xpath("//u:serverDetail/u:apiEnv"));
Output:
array(1) {
[0]=>
object(SimpleXMLElement)#2 (1) {
[0]=>
string(7) "sandbox"
}
}
Edit: Dirty workaround, might be helpful though:
$xml = simplexml_load_file($url);
$xmlStr = str_replace("xmlns", "ns", $xml->asXML());
$xml = new SimpleXMLElement($xmlStr);
var_dump($xml->xpath("serverDetail/apiEnv"));
I've created a simple XML document that will hold information on numerous cities.
<?xml version="1.0" encoding="ISO-8859-1"?>
<config>
<city>
<id>London</id>
</city>
<city>
<id>New York</id>
</city>
</config>
I'm trying to extract the city elements and place them into an array. I have the following so far and the output is simply Array when I call the function.
<?php
$configFile = 'cityConfig.xml';
function getCityConfig($configFile) {
$xml = new SimpleXmlElement(file_get_contents("cityConfig.xml"));
$cities = array();
$cityId = $xml->city[0]->id;
array_push($cities, $cityId);
$cityId = $xml->city[1]->id;
array_push($cities, $cityId);
//var_dump($cities);
return $cities;
}
//print_r(getCityConfig($configFile));
echo getCityConfig($configFile);
?>
var_dump suggests that values are being added into the array.
array(2) { [0]=> object(SimpleXMLElement)#2 (1) { [0]=> string(6) "London" } [1]=> object(SimpleXMLElement)#4 (1) { [0]=> string(8) "New York" } } Array
I'm trying to achieve something along these lines.
$cities = array(
'London',
'New York',
'Paris'
);
The array indexes are called in my index.php to display content.
$pageIntroductionContent = 'The following page brings twin cities together. Here you will find background information on ' . $cities[0] . ', ' . $cities[1] . ' and ' . $cities[2] . '.';
Any ideas where I'm going wrong?
Thanks in advance.
The fact is that in SimpleXMLElement object, all the data is represented as an object, including attributes (as your var_dump suggests, in fact). So, you can get strings by casting these object, because they implement a _toString() method I think. Try:
$cityId = (string) $xml->city[0]->id;
It should work.
Since GMail made it possible to import and export the mail filters, I'd like to manage the XML files that are exported from GMail using a PHP script, as there are some known issues with the number of characters in the search filters.
I've found the simplexml_load_file function in PHP, and have performed var_dump() against the performed export, but I now don't seem to be able to access the apps namespace within the generated XML file.
Following various pages within the PHP manual, I created this very simple script to read the XML out so I can start to process out the filters I've already created. Unfortunately, it seems to be missing the key parts!
<pre><?php
if(file_exists("mailfilters.xml")) {
$xml = simplexml_load_file("mailfilters.xml");
$namespaces = $xml->getNamespaces(true);
foreach ($namespaces as $prefix => $ns) {
$xml->registerXPathNamespace($prefix, $ns);
}
var_dump($xml);
} else {
die("Failed to open filter file");
}
?></pre>
This returns this data (extract)
["entry"]=>
array(268) {
[0]=>
object(SimpleXMLElement)#3 (5) {
["category"]=>
object(SimpleXMLElement)#271 (1) {
["#attributes"]=>
array(1) {
["term"]=>
string(6) "filter"
}
}
["title"]=>
string(11) "Mail Filter"
["id"]=>
string(45) "tag:mail.google.com,2008:filter:1284991916868"
["updated"]=>
string(20) "2010-10-28T11:59:31Z"
["content"]=>
object(SimpleXMLElement)#272 (0) {
}
}
[1]=>
object(SimpleXMLElement)#4 (5) {
["category"]=>
object(SimpleXMLElement)#272 (1) {
["#attributes"]=>
array(1) {
["term"]=>
string(6) "filter"
}
}
["title"]=>
string(11) "Mail Filter"
["id"]=>
string(45) "tag:mail.google.com,2008:filter:1284991925003"
["updated"]=>
string(20) "2010-10-28T11:59:31Z"
["content"]=>
object(SimpleXMLElement)#271 (0) {
}
}
Here's an extract from the XML file I have downloaded today, used to create the above output:
<?xml version='1.0' encoding='UTF-8'?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:apps='http://schemas.google.com/apps/2006'>
<title>Mail Filters</title>
<id>tag:mail.google.com,2008:filters:1284991916868,...,1287734777820</id>
<updated>2010-10-28T11:59:31Z</updated>
<author>
<name>My Name</name>
<email>my#email.addr.es</email>
</author>
<entry>
<category term='filter'></category>
<title>Mail Filter</title>
<id>tag:mail.google.com,2008:filter:1284991916868</id>
<updated>2010-10-28T11:59:31Z</updated>
<content></content>
<apps:property name='from' value='an#email.addr.es'/>
<apps:property name='shouldArchive' value='true'/>
<apps:property name='shouldTrash' value='true'/>
</entry>
<entry>
<category term='filter'></category>
<title>Mail Filter</title>
<id>tag:mail.google.com,2008:filter:1284993579743</id>
<updated>2010-10-28T11:59:31Z</updated>
<content></content>
<apps:property name='subject' value='Some Relevant Subject'/>
<apps:property name='label' value='MyCoolLabel'/>
<apps:property name='shouldArchive' value='true'/>
</entry>
Other "apps:property" verbs include:
<apps:property name='hasTheWord' value=''/>
<apps:property name='shouldAlwaysMarkAsImportant' value=''/>
<apps:property name='doesNotHaveTheWord' value=''/>
I recently had a similar "problem". I was trying to get the email signature settings from Google Apps. This is what the XML Response from Google looks like:
<?xml version='1.0' encoding='UTF-8'?>
<entry xmlns='http://www.w3.org/2005/Atom' xmlns:apps='http://schemas.google.com/apps/2006'>
<id>https://apps-apis.google.com/a/feeds/emailsettings/2.0/domain.com/user/signature</id>
<updated>2012-08-31T15:22:03.067Z</updated>
<link rel='self' type='application/atom+xml' href='https://apps-apis.google.com/a/feeds/emailsettings/2.0/domain.com/user/signature?xoauth_requestor_id=user#domain.com'/>
<link rel='edit' type='application/atom+xml' href='https://apps-apis.google.com/a/feeds/emailsettings/2.0/domain.com/user/signature?xoauth_requestor_id=user#domain.com'/>
<apps:property name='signature' value='Here goes the email signature...'/>
</entry>
I was not able the get the attributes out of apps:property using the SimpleXMLElement. This is how i finally solved it:
// create SimpleXMLElement with XML input as string
$xml = new SimpleXMLElement($feed);
// get namespace from XML
$namespaces = $xml->getNamespaces(true);
// get children (using namespace) and attributes
$appsProperty = $xml->children($namespaces['apps'])->attributes();
// attributes are now stored in array $appsProperty and can be accessed
echo "Name: ".$appsProperty['name'];
echo "Signature: ".$appsProperty['value'];
Jon,
Full marks for linking this from Facebook, I'd never have seen it otherwise and I was doing EXACTLY this yesterday, for a google service!! I think using XPath is a bit of a red herring, let me show you how to access the elements and hopefully it will give you enough information for what you want to do.
You're on the right tracks with $xml->getNamespaces() - but don't iterate there, you need to use the namespace you want on the parent element you want. Firstly, you need to work only on the entry elements, since these are the majority, you might as well loop and check if you have the right one:
foreach($xml as $tag) {
if($tag->getName() == "entry") {
// awesome, do Cool Stuff (TM) here
}
}
Now, you have the element in the $tag variable, and you want the apps: namespaced child elements. So do this:
$tag->getChildren($namespaces['apps']);
When you iterate over that collection, you will see the info you wanted.
HTH,
Lorna
Sample XML:
<root>
<ratings>3</ratings>
<ratings>5</ratings>
<ratings>7</ratings>
</root>
The following code is the basis for my small application, it works as would be expected:
<?php
// $xml is some simplexml object
sizeof($xml->ratings); //3
foreach($xml->ratings as $rating){
echo($rating->value."::"); //this echoes all 3 rating values: 3::5::7
}
?>
This next code, which I would normally consider to be equivalent is not. And I have no idea why:
<?php
// $xml is some simplexml object
$ratings = $xml->ratings;
sizeof($ratings); //3, all is well so far
foreach($ratings as $rating){
echo($rating."::");
/*this echoes a never-ending list of ratings,
looking like 3::5::5::5::5::5::5::5...... */
}
?>
My feeling is that the assignment operator is casting the array of simplexml objects (ratings objects) as something odd, but have no clue as to how.
Other little hints:
var_dump($xml);
/* Output is:
object(SimpleXMLElement)#7 (1) {
["ratings"]=>
array(3) {
[0]=>
string(1) "3"
[1]=>
string(1) "5"
[2]=>
string(1) "7"
}
}
*/
var_dump($ratings);
/* Output is:
object(SimpleXMLElement)#6 (1) {
[0]=>
string(1) "3"
}
*/
Your echos are not the same:
echo($rating."::");
should be
echo($rating->value."::");
Ok, cleaning up some of my own work. After attempting to simplify my issue more, I was not able to prove it. After messing with the actual code, I assume this means I have some sort of mutating object elsewhere in my app that is going bonkers and creating weird results in this xml parsing. Sorry for the confusion and needless question (I guess this proves why i'm trying to refactor some of my complexity out of this app).
As a parting gift, here is the test-suite of code that I used (from simple to more realistic) that I used to prove that all worked as advertised:
<?php
$string = <<<XML
<?xml version='1.0'?>
<root>
<ratings>3</ratings>
<ratings>5</ratings>
<ratings>7</ratings>
</root>
XML;
$xml = simplexml_load_string($string);
var_dump($xml);
echo("Size:".sizeof($xml->ratings)."\n");
foreach($xml->ratings as $rating){
echo($rating."::");
}
echo("\n"."------"."\n");
$ratings = $xml->ratings;
echo("Size:".sizeof($ratings)."\n");
foreach($ratings as $rating){
echo($rating."::");
}
echo("\n\n\n\n"."||||New Example||||"."\n\n\n\n");
$stringthree = <<<XML
<root attr1="val" attr2="desc">
<field-one>val</field-one>
<elm-two attr-name="foo">elmTwoVal1</elm-two>
<elm-three>elmThreeVal1</elm-three>
<elm-two attr-name="bar">elmTwoVal2</elm-two>
<elm-three>elmThreeVa2</elm-three>
<elm-two attr-name="bear">elmTwoVal3</elm-two>
<elm-three>elmThreeVal3</elm-three>
</root>
XML;
$xmlthree = simplexml_load_string($stringthree);
var_dump($xmlthree);
echo("Size:".sizeof($xmlthree->{'elm-two'})."\n");
foreach($xmlthree->{'elm-two'} as $elm){
echo($elm."::");
}
echo("\n"."------"."\n");
$elmMain = $xmlthree->{'elm-two'};
echo("Size:".sizeof($elmMain)."\n");
foreach($elmMain as $elm){
echo($elm."::");
}
?>