How can I call to $item["@attributes"]["tag"]?
I receive the Fatal error: Cannot use string offset as an array in line:
if ($item["@attributes"]["tag"] == $field)
My steps: I receiving XML string, extract it to SimpleXMLObject:
object(SimpleXMLElement)#6 (1)
{
["rec"]=> object(SimpleXMLElement)#7 (1)
{
["datafield"]=> array(1) {
[0]=> object(SimpleXMLElement)#10 (3)
{
["@attributes"]=> array(1) {
["tag"]=> string(2) "99"
}
["@attributes"]=> array(1) {
["tag"]=> string(3) "100"
}
["subfield"]=> array(3) {
[0]=> string(5) "text0"
[1]=> string(5) "text1"
[2]=> string(4) "test"
}
}
}
}
}
Because I have no attribute [code] in SimpleXMLObject I convert it to array, to find the [tag]="100" and change ["code"] or if code=z not exist create it and insert value that I should change or create:
array(1) {
["hold"]=> array(1) {
["rec"]=> array(1){
["datafield"]=> array(2) {
[0]=> array(2)
{
["subfield"]=> array(1) {
[0]=> array(2) {
["@value"]=> string(4) "test"
["@attributes"]=> array(1){
["code"]=> string(1) "z"
}
}
}
["@attributes"]=> array(1) {
["tag"]=> string(3) "100"
}
}
}
}
}
}
This is my PHP code to access the array:
foreach ($xml_ray['hold']['rec'] as $key_item => $item) {
if ($item["@attributes"]["tag"] == $field) { // Line where I get the ERROR
foreach ($item['subfield'] as $key_subfield => $subfield) {
$code = $subfield['@attributes']['code'];
$value = $subfield['@value'];
// ....
if ($checksum==2 && $code==$subfield_file) {
$checksum++;
}
if ($checksum == 3) { $xml_hold_ray['hold']['rec'][$key_item]['subfield'][$key_subfield]['@value'] = $new_code;
}
}
}
}
The Origin XML:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<hold>
<rec>
<datafield ind1=" " ind2=" " tag="99">
<subfield code="a">text</subfield>
</datafield>
<datafield ind1="1" ind2=" " tag="100">
<subfield code="b">text0</subfield>
<subfield code="c">text1</subfield>
<subfield code="z">test2</subfield>
</datafield>
</rec>
</hold>
The whole code for Understand the work of it:
foreach ($xml_ray['hold']['rec'] as $key_item => $item) {
if ($item["@attributes"]["tag"] == $field) {
$info_msg = "FIELD: $field <br />";
$outcame_msg .="Found correct field $field<br />";
foreach ($item['subfield'] as $key_subfield => $subfield) {
$code = $subfield['@attributes']['code'];
$value = $subfield['@value'];
$info_holding_msg.="$code = $value<br />";
if ($value==$li) {
$outcame_msg .= "Found correct li in subfield $code<br />";
$checksum++;
}
if ($value==$loc) {
$outcame_msg .= "Found correct loc in subfield $code<br />";
$checksum++;
}
if ($checksum==2 && $code==$subfield_file) {
$outcame_msg .= "Found subfield $code with value: $value<br />";
$checksum++;
}
if ($checksum == 3) {
$xml_ray['hold']['rec'][$key_item]['subfield'][$key_subfield]['@value'] = $new_code;
$outcame_msg.="data found, changing data accepted.";
}
}
}
}
Update new XML:
$data ='<holds total="4">
<hold link="#">
<hold_id>0000000000000000</hold_id>
<lib desc="Lib">text</lib>
<loc desc="Lib2">text1</loc>
<sup>false</sup>
</hold>
<hold link="#">
<hold_id>0000000000000000</hold_id>
<lib desc="Lib">text</lib>
<loc desc="Lib2">text1</loc>
<sup>false</sup>
</hold>
<hold link="#">
<hold_id>0000000000000000</hold_id>
<lib desc="Lib">text3</lib>
<loc desc="Lib2">text4</loc>
<sup>false</sup>
</hold>
</holds>';
Using SimpleXML, this is how to access the data
$data = <<< XML
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<hold>
<rec>
<datafield ind1=" " ind2=" " tag="99">
<subfield code="a">text</subfield>
</datafield>
<datafield ind1="1" ind2=" " tag="100">
<subfield code="b">text0</subfield>
<subfield code="c">text1</subfield>
<subfield code="z">test2</subfield>
</datafield>
</rec>
</hold>
XML;
$xml_ray = simplexml_load_string($data);
// A test value
$field = "100";
$checksum=2;
$new_code = 't1';
$subfield_file="z";
// Loop through all the <datafield> elements
foreach ( $xml_ray->rec->datafield as $item ) {
if ( $item['tag'] == $field ) {
$replaced = false;
foreach ($item->subfield as $subfield) {
if ($subfield['code']==$subfield_file) {
$subfield[0] = $new_code;
$replaced = true;
}
}
if ( $replaced == false ) {
$newItem = $item->addChild("subfield", $new_code);
$newItem->addAttribute("code", $subfield_file);
}
}
}
See the way you use ->rec
to access the sub elements and ['tag']
to access the attributes.
I'm not 100% sure about what your doing with the middle bit of code, but I've tried to add in what I think your doing. This code doesn't add it in if it doesn't exist and I'm not sure how the $checksum
field processing works.
Two examples of how to use XPath...
$match = $xml_ray->xpath("//datafield[subfield[@code='z']]");
if ( count($match) > 0 ) {
echo "Found match";
}
else {
echo "No match found";
}
$match = $xml_ray->xpath("//datafield[@tag='100'][subfield[@code='z1']]");
if ( count($match) > 0 ) {
echo "Found match";
}
else {
echo "No match found";
}
The first (//datafield[subfield[@code='z']]
) matches any datafield element with a subfield which has an attrbute code with a value of 'z'. This finds an element so prints 'Found Match'.
The second (//datafield[@tag='100'][subfield[@code='z1']]
) matches any datafield element which has a tag attribute = 100 and a subfield with code = 'z1'. This doesn't find an element so prints 'No match found'.
Update: If you want to select the value of the datafield element with attribute tag = 100 and sibfield with code="z", then...
$match = $xml_ray->xpath("//datafield[@tag='100']/subfield[@code='z']");
echo (string)$match[0];
I've changed the XPath slightly from before, but this XPath gives...
test2