Как выполнить запрос, сгруппировать строки набора результатов и преобразовать в XML? - PullRequest
0 голосов
/ 28 января 2020

У меня проблема. Я сделал следующий код для создания массива для XML, который я хочу:

$BusinessId = $_GET["businessid"];
$CustomerCode = $_GET["customerid"];

$sql = "SELECT * FROM Customers WHERE Code=".$CustomerCode." AND BusinessId=".$BusinessId;
$result = $conn->query($sql);
$row = mysqli_fetch_assoc($result);

$CustomerId = $row["Id"];
$sql = "SELECT * FROM Albums WHERE CustomerId=".$CustomerId." ORDER BY Id DESC";
$result1 = $conn->query($sql);

$arr_albums = array();

while ($row1 = mysqli_fetch_assoc($result1))
{
    $arr_images = array();

    $sql = "SELECT * FROM ImagesWithAlbum WHERE AlbumId=".$row1["Id"]." ORDER BY ImageId ASC";
    $result2 = $conn->query($sql);
    while ($row2 = mysqli_fetch_assoc($result2))
    {
        $sql = "SELECT * FROM Images WHERE Id=".$row2["ImageId"];
        $result3 = $conn->query($sql);
        $row3 = mysqli_fetch_assoc($result3);

        $image_array = array(
        array(
            'Id'=>$row3["Id"],
            'Name'=>$row3["Name"])
        );

        $arr_images[] = $image_array;
    }

    $album_array = array(
        array(
            'Id'=>$row1["Id"],
            'Image'=>$arr_images)
        );

    $arr_albums[] = $album_array;
}

Теперь я хочу создать XML из этого массива, поэтому я создал этот код:

function toXml(SimpleXMLElement $xml, array $data, $mainKey = null)
{   
    foreach ($data as $key => $value) {
        // if the key is an integer, it needs text with it to actually work.
        if (is_numeric($key)) {
            $key = $mainKey ? : "key_$key";
        }
        if (is_array($value)) {
            $childXml = $xml->addChild($key);
            toXml($childXml, $value);
        } else {
            $xml->addChild($key, $value);
        }   
    }   
    return $xml;
}

// Pretty print Xml
function formatXml($simpleXMLElement)
{
    $xmlDocument = new DOMDocument('1.0');
    $xmlDocument->preserveWhiteSpace = false;
    $xmlDocument->formatOutput = true;
    $xmlDocument->loadXML($simpleXMLElement->asXML());

    return $xmlDocument->saveXML();
}

$xml = toXml(new SimpleXMLElement('<Albums/>'), $arr_albums, 'Album');
$output = $xml->asXML();

header('Content-Type: text/xml');
print formatXml($xml);

Проблема в том, что xml почти так же, как я хочу, за исключением 1 тега в XML. Теги следующие:

<Albums>
<Album>
<Id>4</Id>
<Images>
<key_0>
<Image>
<Id>2</Id>
<Name>viktor_rood.png</Name>
</Image>
</key_0>
<key_1>
<Image>
<Id>5</Id>
<Name>viktor_geel.png</Name>
</Image>
</key_1>
<key_2>
<Image>
<Id>7</Id>
<Name>viktor_paars.png</Name>
</Image>
</key_2>
<key_3>
<Image>
<Id>8</Id>
<Name>viktor_aqua.png</Name>
</Image>
</key_3>
</Images>
</Album>
</Albums>

Теперь, как мне удалить тег key_x, потому что он мне не нужен!

Что я делаю не так?

Ответы [ 2 ]

2 голосов
/ 28 января 2020

Вы выдвигаете ненужный уровень массива до $image_array и $album_array, что приводит к появлению тегов key_*. Если вы удалите его, он должен избавиться от этих ключей:

$image_array = array(
    'Id'=>$row3["Id"],
    'Name'=>$row3["Name"]
);

$album_array = array(
    'Id'=>$row1["Id"],
    'Images'=>$arr_images
);

Вам также нужно изменить функцию toXML, чтобы она выдавала значение $mainkey при повторном выполнении. В этой версии я выбрал удаление последнего символа с текущего ключа (поэтому для Images вы бы получили Image тегов под ними):

function toXml(SimpleXMLElement $xml, array $data, $mainKey = null)
{   
    foreach ($data as $key => $value) {
        // if the key is an integer, it needs text with it to actually work.
        if (is_numeric($key)) {
            $key = $mainKey ? : "key_$key";
        }
        if (is_array($value)) {
            $childXml = $xml->addChild($key);
            toXml($childXml, $value, substr($key, 0, -1));
        } else {
            $xml->addChild($key, $value);
        }   
    }   
    return $xml;
}

Для ваших данных вы должны получить Результат такой:

<?xml version="1.0"?>
<Albums>
  <Album>
    <Id>4</Id>
    <Images>
      <Image>
        <Id>2</Id>
        <Name>viktor_rood.png</Name>
      </Image>
      <Image>
        <Id>5</Id>
        <Name>viktor_geel.png</Name>
      </Image>
      <Image>
        <Id>7</Id>
        <Name>viktor_paars.png</Name>
      </Image>
      <Image>
        <Id>8</Id>
        <Name>viktor_aqua.png</Name>
      </Image>
    </Images>
  </Album>
</Albums>

Демонстрация на 3v4l.org

0 голосов
/ 29 января 2020
  • Готовая выписка? Проверка.
  • JOIN предложения? Проверка.

...

  • Вложенные циклы? Ушел.
  • Повторные запросы? Ушел.
  • Временные манипуляции с ключами? Ушел.
  • Рекурсия? Ушел.

TBH, я не проверял запрос и не выполняю большую часть XML работы. Если что-то не так, я рад это исправить. Посмотрите, насколько чистым, безопасным и читабельным может быть ваш сценарий ...

Частично код: ( Демонстрация из примера набора результатов ) ( Демонстрация со вторым альбомом )

function formatXml($simpleXMLElement) {
    $xmlDocument = new DOMDocument('1.0');
    $xmlDocument->preserveWhiteSpace = false;
    $xmlDocument->formatOutput = true;
    $xmlDocument->loadXML($simpleXMLElement->asXML());
    return $xmlDocument->saveXML();
}

if (isset($_GET["businessid"], $_GET["customerid"])) {
    $sql = "SELECT Albums.Id, Images.Id, Images.Name
            FROM Customers
            JOIN Albums ON Customer.Id = Albums.CustomerId
            JOIN ImagesWithAlbum ON Albums.Id = ImagesWithAlbum.AlbumId
            JOIN Images ON ImagesWithAlbum.ImageId = Images.Id
            WHERE Customers.Code = ? AND Customers.BusinessId = ?
            ORDER BY Id DESC, ImageId";
    $stmt = $conn->prepare($sql);
    $stmt->bind_param("ss", $_GET["businessid"], $_GET["customerid"]); // use 'ii' if both integers
    $stmt->execute();
    $stmt->bind_result($albumId, $imageId, $imageName);
    $albums = new SimpleXMLElement('<Albums/>');
    $currentAlbumId = null;
    while ($stmt->fetch()) {
        if ($currentAlbumId !== $albumId) {
            $album = $albums->addChild('Album');
            $album->addChild('Id', $albumId);
            $images = $album->addChild('Images');
        }
        $image = $images->addChild('Image');
        $image->addChild('Id', $imageId)
        $image->addChild('Name', $imageName);
        $currentAlbumId = $albumId;
    }
    echo formatXml($albums);
}

Вывод:

<?xml version="1.0"?>
<Albums>
  <Album>
    <Id>4</Id>
    <Images>
      <Image>
        <Id>2</Id>
        <Name>viktor_rood.png</Name>
      </Image>
      <Image>
        <Id>5</Id>
        <Name>viktor_geel.png</Name>
      </Image>
      <Image>
        <Id>7</Id>
        <Name>viktor_paars.png</Name>
      </Image>
      <Image>
        <Id>8</Id>
        <Name>viktor_aqua.png</Name>
      </Image>
    </Images>
  </Album>
</Albums>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...