PHP

2009-04-14 4 views
21

में DOMDocument के साथ इंडेंटेशन मैं नई XML फ़ाइल उत्पन्न करने के लिए DOMDocument का उपयोग कर रहा हूं और मैं फ़ाइल के आउटपुट को अच्छी तरह से इंडेंट करना चाहता हूं ताकि मानव पाठक के लिए इसका पालन करना आसान हो।PHP

उदाहरण के लिए, जब DOMDocument आउटपुट इस डेटा:

<?xml version="1.0"?> 
<this attr="that"><foo>lkjalksjdlakjdlkasd</foo><foo>lkjlkasjlkajklajslk</foo></this> 

मैं एक्सएमएल फ़ाइल होना चाहते हैं:

<?xml version="1.0"?> 
<this attr="that"> 
    <foo>lkjalksjdlakjdlkasd</foo> 
    <foo>lkjlkasjlkajklajslk</foo> 
</this> 

मैं अधिक के लिए उत्तर की तलाश में खोज कर रहा है, और सब कुछ है कि मैं ऐसा लगता है कि इस तरह सफेद जगह को नियंत्रित करने का प्रयास करने के लिए कहा जाता है:

$foo = new DOMDocument(); 
$foo->preserveWhiteSpace = false; 
$foo->formatOutput = true; 

लेकिन ऐसा कुछ नहीं लगता है। शायद एक्सएमएल पढ़ने पर यह केवल काम करता है? ध्यान रखें मैं नए दस्तावेज़ लिखने की कोशिश कर रहा हूं।

क्या ऐसा करने के लिए DOMDocument पर कोई भी अंतर्निहित है? या एक ऐसा कार्य जो इसे आसानी से पूरा कर सकता है?

+1

मुझे यकीन नहीं है कि सवाल क्या है। जो कोड आप दिखाते हैं वह वह आउटपुट देगा जो आप मांग रहे हैं। सबूत: http://codepad.org/4UGyRspx और http://codepad.org/bLTOFQrp - क्या आप इंडेंटेशन स्तर के बारे में पूछ रहे हैं, उदा। इस्तेमाल की गई रिक्त स्थान की संख्या? – Gordon

+0

यहां एक अच्छा सीधा फ़ंक्शन (नियमित अभिव्यक्तियों के आधार पर) है: [PHP के साथ एक्सएमएल प्रारूप] (http://recurser.com/articles/2007/04/05/format-xml-with-php/) – Tomalak

+0

संबंधित जब तक इंडेंटेशन का संबंध है: [preg_replace (कोई कॉलबैक) के साथ इंडेंटेशन को परिवर्तित करना] (http://stackoverflow.com/questions/8616594/converting-indentation-with-preg-replace-no-callback) – hakre

उत्तर

3

मैं अलग अलग तरीकों से 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>"; 
?> 
+0

आपका कोड ठीक काम करता है, लेकिन यह मेरे लिए इसे स्थापित करने के तरीके से मेरे लिए काम नहीं करता है। मेरे पास एक वर्ग xml है और उस कक्षा के अंदर मैं एक चर $ $-> xml बनाता हूं जिसमें DOMDocument का एक उदाहरण होता है, और ऐसा लगता है कि यह सेटअप के साथ काम नहीं करता है। मैं केवल रिक्त स्थान की बजाय वास्तविक टैब भी पसंद करूंगा। –

+0

यह तब एक विशेष मामले की तरह लगता है। मैंने एक सदस्य के रूप में "xml" के साथ एक साधारण वर्ग बनाया, और यह अभी भी काम करता है। बहुत सारे कारक हैं और आपके सटीक कोड के बिना (या एक सरलीकृत संस्करण जो अभी भी आपके लिए विफल रहता है) पुन: उत्पन्न करना असंभव होगा। –

+0

आपकी मदद जॉन के लिए धन्यवाद। मैंने एक मूल इंडेंटेशन फ़ंक्शन लिखा है जो मेरी समस्या को ठीक से ठीक करेगा (अगर आप एक नज़र रखना चाहते हैं तो इसे उत्तर के रूप में पोस्ट करने के बारे में)। –

7

जॉन से कुछ मदद की और अपने दम पर इस के साथ चारों ओर खेलने के बाद, ऐसा लगता है कि यहां तक ​​कि DOMDocument के प्रारूपण के लिए निहित समर्थन मेरी जरूरतों को पूरा नहीं किया। तो, मैंने अपना इंडेंटेशन फ़ंक्शन लिखने का फैसला किया।

यह एक बहुत ही क्रूड फ़ंक्शन है जिसे मैंने तुरंत एक साथ फेंक दिया, इसलिए अगर किसी के पास सामान्य रूप से इसके बारे में कोई ऑप्टिमाइज़ेशन टिप्स या कुछ भी कहना है, तो मुझे यह सुनकर खुशी होगी!

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; 
} 
+2

एक त्वरित टिप्पणी: टैब बनाने के लिए str_repeat() है। बाकी का काम मेरे लिए काफी ठीक लगता है। आप मुझे मिली एक छोटी प्रदर्शन तुलना स्थापित कर सकते हैं। एक वैकल्पिक विचार के रूप में, आप स्ट्रैटोक() को इनपुट को टोकननाइज़ करने के लिए उपयोग कर सकते हैं (प्रतिस्थापित/विस्फोट के बजाय)। – Tomalak

+0

धन्यवाद! मैं वास्तव में उस कार्य को पसंद करता हूं जो आपने स्वयं से बेहतर पाया है, जैसा कि मैंने पाया है कि यह फ़ॉर्मेटिंग को गहराई से गहरा बनाता है। और मुझे कभी भी str_repeat() या strtok() के बारे में पता नहीं था, इसलिए इसके लिए भी धन्यवाद! –

-2
header("Content-Type: text/xml"); 

$str = ""; 
$str .= "<customer>"; 
$str .= "<offer>"; 
$str .= "<opened></opened>"; 
$str .= "<redeemed></redeemed>"; 
$str .= "</offer>"; 
echo $str .= "</customer>"; 

आप किसी भी .xml के अलावा अन्य एक्सटेंशन का उपयोग कर रहे हैं तो पहले सही मान के लिए शीर्ष लेख Content-Type हैडर निर्धारित किया है।

1

xml प्रिंट करते समय आप किस विधि को कॉल करते हैं?

मैं इस का उपयोग करें:

$doc = new DOMDocument('1.0', 'utf-8'); 
$root = $doc->createElement('root'); 
$doc->appendChild($root); 

(...)

$doc->formatOutput = true; 
$doc->saveXML($root); 

यह पूरी तरह से काम करता है, लेकिन केवल तत्व बाहर प्रिंट, तो आप <?xml ... ?> हिस्सा मैन्युअल प्रिंट चाहिए ..

24

DOMDocument चाल करना होगा, मैं व्यक्तिगत रूप से खर्च Googling और इस पता लगाने की कोशिश और मैं ने कहा कि अगर आप

$xmlDoc = new DOMDocument(); 
$xmlDoc->loadXML ($xml); 
$xmlDoc->preserveWhiteSpace = false; 
$xmlDoc->formatOutput = true; 
$xmlDoc->save($xml_file); 

का उपयोग करने वाले के लिए, यह सिर्फ काम नहीं करता है लेकिन, अगर घंटे की जोड़ी एक आकर्षण की तरह

$xmlDoc = new DOMDocument(); 
$xmlDoc->preserveWhiteSpace = false; 
$xmlDoc->formatOutput = true; 
$xmlDoc->loadXML ($xml); 
$xmlDoc->save($archivoxml); 

वर्क्स उम्मीद है कि इस मदद करता है एक्सएमएल पाठ प्रवाह के साथ इस विषय सौदे में

+2

दोस्त! आपने धमाल मचाया! इसे तलाशने के लिए धन्यवाद! –

+3

डेमिट ... यह केवल एक्सएमएल के साथ काम करता प्रतीत होता है, एचटीएमएल अभी भी बदसूरत दिखता है। =/ –

+0

हां, एचटीएमएल – 3zzy

1

अधिकांश उत्तर: आप इस क्रम में एक ही कोड लेकिन का उपयोग करें। इंडेंटेशन जॉब करने के लिए डोम कार्यक्षमताओं का उपयोग करके एक और तरीका है। loadXML() dom विधि xml स्रोत में टेक्स्ट नोड्स के रूप में मौजूद इंडेंटेशन वर्ण आयात करता है। विचार है कि डोम से ऐसे टेक्स्ट नोड्स को निकालना है और फिर सही ढंग से स्वरूपित किए गए हैं (अधिक जानकारी के लिए नीचे दिए गए कोड में टिप्पणियां देखें)।

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 
-1

यो peeps,

बस पता चला कि जाहिरा तौर पर, एक रूट XML तत्व पाठ बच्चों को शामिल नहीं हो सकता है: नीचे यह कैसे उपयोग करने के लिए की एक पूरी उदाहरण है। यह nonintuitive ए है। च। लेकिन जाहिर है, उदाहरण के लिए,

इंडेंट करने में विफल रहेगा।

https://bugs.php.net/bug.php?id=54972

तो वहाँ तुम जाओ, ज। टी। एच। आदि।

संबंधित मुद्दे