PHP DOM — Как перебрать xpath в массив с parent / children / child?

Я новичок в использовании DOM с PHP и мне нужна помощь в поиске решения итерации xpath в массив. Примеры, которые я нашел в Интернете, оказали очень небольшую помощь.

Это содержимое строки из моего файла XML:

    <x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 5.2-c004 1.136881, 2010/06/10-18:11:35        ">
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
<rdf:Description
rdf:about=""xmlns:photoshop="http://ns.adobe.com/photoshop/1.0/"xmlns:dc="http://purl.org/dc/elements/1.1/"xmlns:tiff="http://ns.adobe.com/tiff/1.0/"xmlns:exif="http://ns.adobe.com/exif/1.0/"xmlns:xmp="http://ns.adobe.com/xap/1.0/"xmlns:aux="http://ns.adobe.com/exif/1.0/aux/"xmlns:crs="http://ns.adobe.com/camera-raw-settings/1.0/"xmlns:Iptc4xmpCore="http://iptc.org/std/Iptc4xmpCore/1.0/xmlns/"xmlns:xmpRights="http://ns.adobe.com/xap/1.0/rights/"photoshop:LegacyIPTCDigest="B0D1E9B9CFC1C774E7277517B04970DC"photoshop:ColorMode="3"photoshop:ICCProfile="sRGB IEC61966-2.1"photoshop:AuthorsPosition="Tester"photoshop:Headline="Big City Landscape"photoshop:CaptionWriter="Freelancer"photoshop:DateCreated="2016-08-05T02:16Z"photoshop:City="NA"photoshop:State="NA"photoshop:Country="NA"photoshop:TransmissionReference="2323"photoshop:Instructions="set to landscape"photoshop:Credit="Photographor: FirstName lastname"photoshop:Source="Smart Phone Photo"tiff:Make="Motorola"tiff:Model="MB865"tiff:Orientation="1"tiff:ImageWidth="3264"tiff:ImageLength="1840"tiff:PhotometricInterpretation="2"tiff:SamplesPerPixel="3"tiff:XResolution="72/1"tiff:YResolution="72/1"tiff:ResolutionUnit="2"exif:ExifVersion="0220"exif:ExposureTime="1/11"exif:ShutterSpeedValue="3459432/1000000"exif:FNumber="24/10"exif:ApertureValue="2526069/1000000"exif:ExposureProgram="0"exif:BrightnessValue="0/1"exif:ExposureBiasValue="0/10"exif:MaxApertureValue="3/1"exif:SubjectDistance="0/1"exif:MeteringMode="1"exif:LightSource="4"exif:FocalLength="460/100"exif:SceneType="1"exif:CustomRendered="1"exif:ExposureMode="0"exif:WhiteBalance="0"exif:SceneCaptureType="0"exif:GainControl="256"exif:Contrast="0"exif:Saturation="0"exif:Sharpness="0"exif:SubjectDistanceRange="0"exif:DigitalZoomRatio="65536/65535"exif:PixelXDimension="3264"exif:PixelYDimension="1840"exif:ColorSpace="1"xmp:ModifyDate="2016-02-22T09:22:39-05:00"xmp:MetadataDate="2016-08-05T02:21:35-04:00"aux:ApproximateFocusDistance="0/1"crs:AlreadyApplied="True"Iptc4xmpCore:IntellectualGenre="NA"Iptc4xmpCore:Location="NA"Iptc4xmpCore:CountryCode="NA">
<dc:rights>
<rdf:Alt>
<rdf:li xml:lang="x-default">Copyright FirstName lastname</rdf:li>
</rdf:Alt>
</dc:rights>
<dc:creator>
<rdf:Seq>
<rdf:li>FirstName lastname</rdf:li>
</rdf:Seq>
</dc:creator>
<dc:description>
<rdf:Alt>
<rdf:li xml:lang="x-default">Jurks on the move</rdf:li>
</rdf:Alt>
</dc:description>
<dc:subject>
<rdf:Bag>
<rdf:li>New Jurks in Town</rdf:li>
</rdf:Bag>
</dc:subject>
<dc:title>
<rdf:Alt>
<rdf:li xml:lang="x-default">Big City Jurks</rdf:li>
</rdf:Alt>
</dc:title>
<tiff:BitsPerSample>
<rdf:Seq>
<rdf:li>8</rdf:li>
<rdf:li>8</rdf:li>
<rdf:li>8</rdf:li>
</rdf:Seq>
</tiff:BitsPerSample>
<exif:ISOSpeedRatings>
<rdf:Seq>
<rdf:li>107</rdf:li>
</rdf:Seq>
</exif:ISOSpeedRatings>
<exif:Flash exif:Fired="True" exif:Return="0" exif:Mode="1" exif:Function="False" exif:RedEyeMode="False"/>
<Iptc4xmpCore:CreatorContactInfo
Iptc4xmpCore:CiAdrExtadr=""Iptc4xmpCore:CiAdrCity=""Iptc4xmpCore:CiAdrRegion="NY"Iptc4xmpCore:CiAdrPcode=""Iptc4xmpCore:CiAdrCtry="USA"Iptc4xmpCore:CiTelWork=""Iptc4xmpCore:CiEmailWork="you@yourwebsite.com"Iptc4xmpCore:CiUrlWork="www.yourwebsite.com"/>
<Iptc4xmpCore:SubjectCode>
<rdf:Bag>
<rdf:li>Jurks</rdf:li>
</rdf:Bag>
</Iptc4xmpCore:SubjectCode>
<Iptc4xmpCore:Scene>
<rdf:Bag>
<rdf:li>Big City</rdf:li>
</rdf:Bag>
</Iptc4xmpCore:Scene>
<xmpRights:UsageTerms>
<rdf:Alt>
<rdf:li xml:lang="x-default">Free to use</rdf:li>
</rdf:Alt>
</xmpRights:UsageTerms>
</rdf:Description>
</rdf:RDF>
</x:xmpmeta>

Вот как я подхожу к вопросу.

    $__data = "xmp-cache-test.xml";

$content = file_get_contents('xmp-cache-test.xml');

if(preg_match("/(\<x\:xmpmeta.*?\>.*?\<\/x\:xmpmeta\>)/s", $content, $matches))
$data = "<?xml version='1.0'?>\n" . $matches[1];

$myXmlString = $data ;
$myXmlFilename = $__data;

$doc = new DOMDocument();
$doc->loadXML($myXmlString);
$doc->documentURI = $myXmlFilename;
$xpath = new DOMXpath($doc);

$xpath->registerNamespace('x', 'adobe:ns:meta/');
$xpath->registerNamespace('xmp', 'http://ns.adobe.com/xap/1.0/');
$xpath->registerNamespace("Iptc4xmpCore", "http://iptc.org/std/Iptc4xmpCore/1.0/xmlns/");
$xpath->registerNamespace('rdf', 'http://www.w3.org/1999/02/22-rdf-syntax-ns#');

$elements = $xpath->evaluate('//rdf:RDF/rdf:Description');
$arr_xmp = iterator_to_array($elements);
print_r($arr_xmp);

// Результат печати:

    Array (
[0] => DOMElement Object (
[tagName] => rdf:Description
[schemaTypeInfo] =>
[nodeName] => rdf:Description
[nodeValue] => Copyright FirstName lastname FirstName lastname Jurks on the move
New Jurks in Town Big City Jurks 8 8 8 107 Jurks Big City Free to use
[nodeType] => 1
[parentNode] => (object value omitted)
[childNodes] => (object value omitted)
[firstChild] => (object value omitted)
[lastChild] => (object value omitted)
[previousSibling] => (object value omitted)
[nextSibling] => (object value omitted)
[attributes] => (object value omitted)
[ownerDocument] => (object value omitted)
[namespaceURI] => http://www.w3.org/1999/02/22-rdf-syntax-ns# [prefix] => rdf
[localName] => Description
[baseURI] => xmp-cache-test.xml
[textContent] => Copyright FirstName lastname FirstName lastname Jurks on the move
New Jurks in Town Big City Jurks 8 8 8 107 Jurks Big City Free to use
) )

Вышеуказанный результат не соответствует ожиданиям.
Я бы предпочел иметь в массиве для просмотра что-то похожее на следующий пример ниже
и наряду с несколькими другими вариантами:

    Array (
[rdf:about] =>
[xmlns:photoshop] => http://ns.adobe.com/photoshop/1.0/
[xmlns:dc] => http://purl.org/dc/elements/1.1/
[xmlns:tiff] => http://ns.adobe.com/tiff/1.0/
[xmlns:exif] => http://ns.adobe.com/exif/1.0/
[xmlns:xmp] => http://ns.adobe.com/xap/1.0/
[xmlns:aux] => http://ns.adobe.com/exif/1.0/aux/
[xmlns:crs] => http://ns.adobe.com/camera-raw-settings/1.0/
[xmlns:Iptc4xmpCore] => http://iptc.org/std/Iptc4xmpCore/1.0/xmlns/
[xmlns:xmpRights] => http://ns.adobe.com/xap/1.0/rights/
[photoshop:LegacyIPTCDigest] => B0D1E9B9CFC1C774E7277517B04970DC
[photoshop:ColorMode] => 3
[photoshop:ICCProfile] => sRGB IEC61966-2.1
[photoshop:AuthorsPosition] => Tester
[photoshop:Headline] => Big City Landscape
[photoshop:CaptionWriter] => Freelancer
[photoshop:DateCreated] => 2016-08-05T02:16Z
[photoshop:City] => NA
[photoshop:City] => NA
[photoshop:State] => NA
[photoshop:Country] => NA
[photoshop:TransmissionReference] => 2323
[photoshop:Instructions] => set to landscape
[photoshop:Credit] => Photographor: FirstName lastname
[photoshop:Source] => Smart Phone Photo
[tiff:Make] => Motorola
[tiff:Model] => MB865
[tiff:Orientation] => 1

------------ // continue
)
  1. Варианты: приведение примера было бы полезно.

    1. Как я должен подходить к созданию массива с помощью DOM?
    2. Если мне нужно удалить сказать «TIFF и EXIF» из массива, что
      должен ли быть такой подход?
    3. Используйте Dom, чтобы обновить значение «photoshop: Credit».
    4. Как использовать DOM для обращения массива обратно к строке XML.

0

Решение

============= EDIT ===================

От XML до части массива, почти тот же вопрос здесь: Какова лучшая функция php DOM 2 Array?

Я немного поиграл с кодом, и вот результат:

function xml_to_array($root) {
$result = array();

if ($root->hasAttributes()) {
$attrs = $root->attributes;
foreach ($attrs as $attr) {
$result['@attributes'][$attr->name] = $attr->value;
}
}

if ($root->hasChildNodes()) {
$children = $root->childNodes;
if ($children->length == 1) {
$child = $children->item(0);
if ($child->nodeType == XML_TEXT_NODE) {
$result['_value'] = $child->nodeValue;
return count($result) == 1
? $result['_value']
: $result;
}
}
$groups = array();
foreach ($children as $child) {
if($child->nodeType == XML_TEXT_NODE && empty(trim($child->nodeValue))) continue;
if (!isset($result[$child->nodeName])) {
$result[$child->nodeName] = xml_to_array($child);
} else {
if (!isset($groups[$child->nodeName])) {
$result[$child->nodeName] = array($result[$child->nodeName]);
$groups[$child->nodeName] = 1;
}
$result[$child->nodeName][] = xml_to_array($child);
}
}
}

return $result;
}// $content = your xml raw source

if(preg_match("/(\<x\:xmpmeta.*?\>.*?\<\/x\:xmpmeta\>)/s", $content, $matches))
$data = "<?xml version='1.0'?>\n" . $matches[1];

$myXmlString = $data ;
//$myXmlFilename = $__data;

$doc = new DOMDocument();
$doc->loadXML($myXmlString);

$array = xml_to_array($doc);
print_r($array);

Очень аккуратная функция, которую кто-то там написал, она перебирает XML, собирая атрибуты и значения узлов и почти игнорируя боль, связанную с ужасными пространствами имен.

Если вам нужно удалить элемент из массива, просто используйте unset, как в:

unset($array['x:xmpmeta']['rdf:RDF']['rdf:Description']['tiff:BitsPerSample']);

Что касается того, как обновить значение атрибута, точно такой же вопрос здесь: Изменить значение атрибута тега с помощью PHP DOMDocument

$dom = new DOMDocument();
$dom->loadHTML('<a href="http://foo.bar/">Click here</a>');

foreach ($dom->getElementsByTagName('a') as $item) {

$item->setAttribute('href', 'http://google.com/');
echo $dom->saveHTML();
exit;
}

И, наконец, как вернуться обратно из массива в DOM: нет простого способа, вам придется вручную создавать объект DOM и создавать узлы и атрибуты один за другим.

После заселения вы позвоните http://php.net/manual/en/domdocument.savexml.php чтобы получить код XML.

<?php

$doc = new DOMDocument('1.0');
// we want a nice output
$doc->formatOutput = true;

$root = $doc->createElement('book');
$root = $doc->appendChild($root);

$title = $doc->createElement('title');
$title = $root->appendChild($title);

$text = $doc->createTextNode('This is the title');
$text = $title->appendChild($text);

echo "Saving all the document:\n";
echo $doc->saveXML() . "\n";

echo "Saving only the title part:\n";
echo $doc->saveXML($title);

?>

Надеюсь это поможет,

0

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector