замена значений и атрибутов xml на файл json в php - PullRequest
0 голосов
/ 03 июля 2018

Я пытаюсь изменить XML-файл. Пример файла выглядит так

<?xml version="1.0" encoding="UTF-8" ?>
<country>
<display>
    <identification>
        <country>nl</country>
        <identifier>ABC01</identifier>
    </identification>
</display>
<region>
    <publicationTime>2018-04-18T09:45:00Z</publicationTime>
    <publicationCreator>
        <identifier>ABC01</identifier>
    </publicationCreator>
    <tableLoc id="ABC01_SITE_TABLE" version="14"/>
    <measurements>
        <siteLoc id="ABC01_ABC01" version="7"/>
    </measurements>
    <measurements>
        <siteLoc id="ABC01_ABC02" version="7"/>
    </measurements>
    <measurements>
        <siteLoc id="ABC01_ABC03" version="7"/>
    </measurements>
    <measurements>
        <siteLoc id="ABC01_ABC04" version="7"/>
    </measurements>
    <measurements>
        <siteLoc id="ABC01_ABC17" version="7"/>
    </measurements>
    <measurements>
        <siteLoc id="ABC01_ABC19" version="9"/>
    </measurements>
    <measurements>
        <siteLoc id="ABC01_ABC18" version="9"/>
    </measurements>
    <measurements>
        <siteLoc id="ABC01_ABC15" version="7"/>
    </measurements>
    <measurements>
        <siteLoc id="ABC01_ABC09" version="7"/>
    </measurements>
    <measurements>
        <siteLoc id="ABC01_ABC011" version="7"/>
    </measurements>
</region>
</country>

Прежде всего мне нужно было изменить значение тега 2 идентификаторов с

<identifier>ABC01</identifier>

до

<identifier>NLNDW</identifier>

, что удалось. тогда мне пришлось изменить атрибут

<tableLoc id="ABC01_SITE_TABLE" version="14"/>

до

<tableLoc id="NDW_01_MT" version="14"/>

наконец, мне нужно перезаписать все версии атрибутов siteloc соответствующими идентификаторами из файла json:

{
"ABC01": {
    "ABC01_ABC01": 9,
    "ABC01_ABC02": 7,
    "ABC01_ABC03": 4,
    "ABC01_ABC04": 1,
    "ABC01_ABC05": 2,
    "ABC01_ABC06": 16,
    "ABC01_ABC07": 3,
    "ABC01_ABC08": 8,
    "ABC01_ABC09": 7,
    "ABC01_ABC10": 6,
    "ABC01_ABC11": 4,
    "ABC01_ABC12": 3,
    "ABC01_ABC13": 2,
    "ABC01_ABC14": 2,
    "ABC01_ABC15": 2,
    "ABC01_ABC16": 3,
    "ABC01_ABC17": 5,
    "ABC01_ABC18": 5,
    "ABC01_ABC19": 2,
    "ABC01_ABC20": 3,
    "ABC01_ABC21": 5,
    "ABC01_ABC22": 39,
    "ABC01_ABC23": 23,
    "ABC01_ABC24": 13,
    "ABC01_ABC25": 1,
    "ABC01_ABC26": 1,
    "ABC01_ABC27": 3
},
"ABC02": {
    "ABC02_ABC02": 2,
    "ABC02_ABC02": 2,
    "ABC02_ABC02": 2,
    "ABC02_ABC02": 2,
    "ABC02_ABC02": 2,
    "ABC02_ABC02": 2,
    "ABC02_ABC02": 2,
    "ABC02_ABC02": 2,
    "ABC02_ABC02": 2,
    "ABC02_ABC02": 2,
    "ABC02_ABC02": 2,
    "ABC02_ABC02": 2,
    "ABC02_ABC02": 2,
    "ABC02_ABC02": 3,
    "ABC02_ABC02": 2
},
"VWY09": {
    "VWY09_VWY10": 1,
    "VWY09_VWY11": 1,
    "VWY09_VWY12": 1,
    "VWY09_VWY13": 1,
    "VWY09_VWY14": 1,
    "VWY09_VWY15": 1,
    "VWY09_VWY16": 1,
    "VWY09_VWY17": 1,
    "VWY09_VWY18": 1,
    "VWY09_VWY19": 1
},
"GAD02": {
    "GAD02_XRZ01": 2,
    "GAD02_XRZ02": 2,
    "GAD02_XRZ03": 2,
    "GAD02_XRZ04": 2,
    "GAD02_XRZ05": 2,
    "GAD02_XRZ06": 2,
    "GAD02_XRZ07": 2,
    "GAD02_XRZ08": 2
}
}

так например

<measurements>
    <siteLoc id="ABC01_ABC03" version="7"/>
</measurements>

должно стать:

<measurements>
    <siteLoc id="ABC01_ABC03" version="4"/>
</measurements>

мой код таким образом:

$identification = new DomDocument;
$identification2 = new DomDocument;
$identification3 = new DomDocument;
$identification_node = $identification ->createElement('identification');
$identification_node2 = $identification2  ->createElement('publicationCreator');
$identification_node3 = $identification3 ->createElement('tableLoc');

// Add some children
$identification_node->appendChild($identification->createElement('country', 'nl'));
$identification_node->appendChild($identification->createElement('identifier', 'NLNDW'));
$identification_node2->appendChild($identification2->createElement('identifier     ', 'NLNDW'));
$newnode3 = $identification3->appendChild($identification_node3);
$newnode3->setAttribute("align", "left");

$identification->appendChild($identification_node);
$identification2->appendChild($identification_node2);

$dom = new DomDocument;
$dom->loadXML($xml);

$xpath = new DOMXpath($dom);
$xpath1 = new DOMXpath($dom);
$xpath2 = new DOMXpath($dom);


$nodelist = $xpath->query('/country/display/identification');
$nodelist1 = $xpath1->query('/country/region/publicationCreator');
$oldnode = $nodelist->item(0);
$oldnode1 = $nodelist1->item(0);

$newnode = $dom->importNode($identification->documentElement, true);
$newnode1 = $dom->importNode($identification2->documentElement, true);

$oldnode->parentNode->replaceChild($newnode, $oldnode);
$oldnode1->parentNode->replaceChild($newnode1, $oldnode1);

echo $dom->saveXML($dom);
$dom->save('result.xml');

Я знаю, как перебирать xml, но я не знаю, как найти соответствующий атрибут id siteloc в файле json и перезаписать атрибут version siteloc версией из json.

Была бы признательна за помощь

Ответы [ 2 ]

0 голосов
/ 03 июля 2018

Рассмотрим XSLT , язык специального назначения, предназначенный для преобразования файлов XML, таких как замена текста узлов и атрибутов. PHP может запускать сценарии XSLT 1.0 с классом php-xsl , для которого требуется расширение, включенное в файл .ini.

Однако, сначала ваш относительно плоский JSON должен быть преобразован в XML, который PHP может построить, а затем скрипт XSLT будет рекурсивно ссылаться для сопоставления необходимых значений местоположения сайта между документами с помощью функции document(). Обязательно сохраните оба XML-файла (исходный и json-преобразованный) в одном каталоге.

PHP (Преобразованный JSON XML; только место, где используются циклы)

$data = json_decode($site_json, TRUE);

// Create a DOM document 
$dom = new DOMDocument('1.0', 'UTF-8');
$dom->formatOutput = true;
$dom->preserveWhiteSpace = false;

// Create the root element of XML tree
$root = $dom->createElement("site_locations");
$root = $dom->appendChild($root);

// Iterate json elements for child nodes
foreach ($data as $outer) {      
    foreach ($outer as $k=>$v) {  
        $node = $dom->createElement('site');
        $root->appendChild($node);
        $node->setAttribute("id", $k);
        $node->setAttribute("version", $v);
    }
}

// Output XML content to screen
echo $dom->saveXML();
// <?xml version="1.0"?>
// <site_locations>
//   <site id="ABC01_ABC01" version="9"/>
//   <site id="ABC01_ABC02" version="7"/>
//   <site id="ABC01_ABC03" version="4"/>
//   <site id="ABC01_ABC04" version="1"/>
//   <site id="ABC01_ABC05" version="2"/>
//   <site id="ABC01_ABC06" version="16"/>
//   ...

// Output XML content to file
file_put_contents("SiteLocationsLookups.xml", $dom->saveXML());

XSLT Script (сохранить как файл .xsl, специальный файл .xml)

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output indent="yes"/>
  <xsl:strip-space elements="*"/>

  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="identifier">
    <xsl:copy>NLNDW</xsl:copy>
  </xsl:template>

  <xsl:template match="tableLoc">
    <xsl:copy>      
      <xsl:attribute name="id">NDW_01_MT</xsl:attribute>
      <xsl:copy-of select="@version"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="siteLoc">
    <xsl:copy>
      <xsl:variable name="curr_id"><xsl:value-of select="@id"/></xsl:variable>
      <xsl:apply-templates select="@*"/>
      <xsl:attribute name="version">
         <xsl:value-of select="document('SiteLocationsLookups.xml')//site[@id=$curr_id]/@version"/>
      </xsl:attribute>
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

PHP (обработка окончательного XML)

// Load XML and XSLT files
$doc = new DOMDocument();
$doc->load('Input.xml');

$xsl = new DOMDocument;
$xsl->load('XSLT_Script.xsl');              // REFERENCES JSON CONVERTED XML

// Configure the transformer
$proc = new XSLTProcessor;
$proc->importStyleSheet($xsl); 

// Transform XML source
$newXml = $proc->transformToXML($doc);

// Save output to file
file_put_contents('Output.xml', $newXml);

Вывод XML

<?xml version="1.0" encoding="utf-8"?>
<country>
  <display>
    <identification>
      <country>nl</country>
      <identifier>NLNDW</identifier>
    </identification>
  </display>
  <region>
    <publicationTime>2018-04-18T09:45:00Z</publicationTime>
    <publicationCreator>
      <identifier>NLNDW</identifier>
    </publicationCreator>
    <tableLoc id="NDW_01_MT" version="14" />
    <measurements>
      <siteLoc id="ABC01_ABC01" version="9" />
    </measurements>
    <measurements>
      <siteLoc id="ABC01_ABC02" version="7" />
    </measurements>
    <measurements>
      <siteLoc id="ABC01_ABC03" version="4" />
    </measurements>
    <measurements>
      <siteLoc id="ABC01_ABC04" version="1" />
    </measurements>
    <measurements>
      <siteLoc id="ABC01_ABC17" version="5" />
    </measurements>
    <measurements>
      <siteLoc id="ABC01_ABC19" version="2" />
    </measurements>
    <measurements>
      <siteLoc id="ABC01_ABC18" version="5" />
    </measurements>
    <measurements>
      <siteLoc id="ABC01_ABC15" version="2" />
    </measurements>
    <measurements>
      <siteLoc id="ABC01_ABC09" version="7" />
    </measurements>
    <measurements>
      <siteLoc id="ABC01_ABC011" version="" />
    </measurements>
  </region>
</country>
0 голосов
/ 03 июля 2018

Почему вы создаете 4 разных документа DOM? Чтобы заменить данные, которые вам нужны, загрузите исходные данные и замените их.

$document = new DOMDocument();
// load the original data
$document->loadXml($xml);
$xpath = new DOMXpath($document);

// iterate any "identifier" element node
foreach ($xpath->evaluate('//identifier') as $identifier) {
  // change its content
  $identifier->textContent = 'NLNDW';
}
// iterate any "id" attribute of an "tableLoc" node 
foreach ($xpath->evaluate('//tableLoc/@id') as $tableLocId) {
  // change its value
  $tableLocId->value = 'NDW_01_MT';
}

// decode json, force arrays
$map = json_decode($json, TRUE);

// iterate any "siteLoc" element node in the document
foreach ($xpath->evaluate('//siteLoc[@id]') as $siteLocation) {
  // read the "id"attribute
  $id = $siteLocation->getAttribute('id');
  // the json seems to be grouped by the first part
  $groupId = strstr($id, '_', TRUE);
  // check if here is a new value
  if (isset($map[$groupId][$id])) {
    // change the version attribute
    $siteLocation->setAttribute('version', $map[$groupId][$id]);
  } 
}

// output/save the modified document
echo $document->saveXml();
...