Я использовал $priceResult
как массив, содержащий объекты категорий. Я думаю, это выглядело бы примерно так:
$priceResult = array()
foreach($pricing->categories as $category){
$c = new stdClass();
$c->CategoryCode = $category->categoryCode;
$c->CategoryDescription = $category->category_description;
$c->Products = array();
foreach($category->products as $product){
$p = new stdClass();
$p->ProductCode = null; // $product->something? no idea where this is
$p->CountNumber = $product->productInfo->product->product_type->quantDetails;
$p->ProductDescription = $product->productInfo->product->product_type->desc;
$p->PriceAmount = $product->pricing->MainPrice;
$c->Products[] = $p;
}
$priceResult[] = $c;
}
Я должен сказать, что исходные данные, похоже, имеют очень странную структуру.
After some help from John and playing around with this on my own, it seems that even DOMDocument's inherent support for formatting didn't meet my needs. So, I decided to write my own indentation function.
This is a pretty crude function that I just threw together quickly, so if anyone has any optimization tips or anything to say about it in general, I'd be glad to hear it!
function indent($text)
{
// Create new lines where necessary
$find = array('>', '</', "\n\n");
$replace = array(">\n", "\n</", "\n");
$text = str_replace($find, $replace, $text);
$text = trim($text); // for the \n that was added after the final tag
$text_array = explode("\n", $text);
$open_tags = 0;
foreach ($text_array AS $key => $line)
{
if (($key == 0) || ($key == 1)) // The first line shouldn't affect the indentation
$tabs = '';
else
{
for ($i = 1; $i <= $open_tags; $i++)
$tabs .= "\t";
}
if ($key != 0)
{
if ((strpos($line, '</') === false) && (strpos($line, '>') !== false))
$open_tags++;
else if ($open_tags > 0)
$open_tags--;
}
$new_array[] = $tabs . $line;
unset($tabs);
}
$indented_text = implode("\n", $new_array);
return $indented_text;
}
Я попытался запустить приведенный ниже код, установив formatOutput
и preserveWhiteSpace
в другими способами, и единственный член, который имеет какое-либо влияние на вывод, является formatOutput
. Можете ли вы запустить приведенный ниже сценарий и посмотреть, работает ли он?
<?php
echo "<pre>";
$foo = new DOMDocument();
//$foo->preserveWhiteSpace = false;
$foo->formatOutput = true;
$root = $foo->createElement("root");
$root->setAttribute("attr", "that");
$bar = $foo->createElement("bar", "some text in bar");
$baz = $foo->createElement("baz", "some text in baz");
$foo->appendChild($root);
$root->appendChild($bar);
$root->appendChild($baz);
echo htmlspecialchars($foo->saveXML());
echo "</pre>";
?>
Большинство ответов в этой теме посвящено текстовому потоку xml. Вот еще один подход, использующий функции dom для выполнения работы с отступами. Метод loadXML () dom импортирует символы отступов, присутствующие в источнике xml, как текстовые узлы. Идея состоит в том, чтобы удалить такие текстовые узлы из DOM, а затем воссоздать правильно отформатированные (см. Комментарии в коде ниже для более подробной информации).
Функция xmlIndent () реализована как метод класса indentDomDocument, который унаследован от domDocument. Ниже приведен полный пример того, как его использовать:
$dom = new indentDomDocument("1.0");
$xml = file_get_contents("books.xml");
$dom->loadXML($xml);
$dom->xmlIndent();
echo $dom->saveXML();
class indentDomDocument extends domDocument {
public function xmlIndent() {
// Retrieve all text nodes using XPath
$x = new DOMXPath($this);
$nodeList = $x->query("//text()");
foreach($nodeList as $node) {
// 1. "Trim" each text node by removing its leading and trailing spaces and newlines.
$node->nodeValue = preg_replace("/^[\s\r\n]+/", "", $node->nodeValue);
$node->nodeValue = preg_replace("/[\s\r\n]+$/", "", $node->nodeValue);
// 2. Resulting text node may have become "empty" (zero length nodeValue) after trim. If so, remove it from the dom.
if(strlen($node->nodeValue) == 0) $node->parentNode->removeChild($node);
}
// 3. Starting from root (documentElement), recursively indent each node.
$this->xmlIndentRecursive($this->documentElement, 0);
} // end function xmlIndent
private function xmlIndentRecursive($currentNode, $depth) {
$indentCurrent = true;
if(($currentNode->nodeType == XML_TEXT_NODE) && ($currentNode->parentNode->childNodes->length == 1)) {
// A text node being the unique child of its parent will not be indented.
// In this special case, we must tell the parent node not to indent its closing tag.
$indentCurrent = false;
}
if($indentCurrent && $depth > 0) {
// Indenting a node consists of inserting before it a new text node
// containing a newline followed by a number of tabs corresponding
// to the node depth.
$textNode = $this->createTextNode("\n" . str_repeat("\t", $depth));
$currentNode->parentNode->insertBefore($textNode, $currentNode);
}
if($currentNode->childNodes) {
$indentClosingTag = false;
foreach($currentNode->childNodes as $childNode) $indentClosingTag = $this->xmlIndentRecursive($childNode, $depth+1);
if($indentClosingTag) {
// If children have been indented, then the closing tag
// of the current node must also be indented.
$textNode = $this->createTextNode("\n" . str_repeat("\t", $depth));
$currentNode->appendChild($textNode);
}
}
return $indentCurrent;
} // end function xmlIndentRecursive
} // end class indentDomDocument
Йо выглядывает,
только что обнаружил, что, очевидно, корневой элемент XML не может содержать текстовые дочерние элементы. Это не интуитивно понятно. е. Но, по-видимому, это причина того, что, например,
$x = new \DOMDocument;
$x -> preserveWhiteSpace = false;
$x -> formatOutput = true;
$x -> loadXML('<root>a<b>c</b></root>');
echo $x -> saveXML();
не сможет отступить.
https://bugs.php.net/bug.php?id=54972
Итак, поехали, h. т. час и т. д.
header("Content-Type: text/xml");
$str = "";
$str .= "<customer>";
$str .= "<offer>";
$str .= "<opened></opened>";
$str .= "<redeemed></redeemed>";
$str .= "</offer>";
echo $str .= "</customer>";
Если вы используете какое-либо расширение, кроме .xml
, то сначала установите правильное значение заголовка header Content-Type
.