Asked  7 Months ago    Answers:  5   Viewed   34 times

I have an XML file loaded into a DOM document, I wish to iterate through all 'foo' tags, getting values from every tag below it. I know I can get values via

$element = $dom->getElementsByTagName('foo')->item(0);
foreach($element->childNodes as $node){
    $data[$node->nodeName] = $node->nodeValue;
}

However, what I'm trying to do, is from an XML like,

<stuff>
  <foo>
    <bar></bar>
      <value/>
    <pub></pub>
  </foo>
  <foo>
    <bar></bar>
    <pub></pub>
  </foo>
  <foo>
    <bar></bar>
    <pub></pub>
  </foo>
  </stuff>

iterate over every foo tag, and get specific bar or pub, and get values from there. Now, how do I iterate over foo so that I can still access specific child nodes by name?

 Answers

51

Not tested, but what about:

$elements = $dom->getElementsByTagName('foo');
$data = array();
foreach($elements as $node){
    foreach($node->childNodes as $child) {
        $data[] = array($child->nodeName => $child->nodeValue);
    }
}
Wednesday, March 31, 2021
 
makadev
answered 7 Months ago
49

The answer is that it doesn't actually need any escaping according to the spec (skipping the mentions of CDATA):

The ampersand character (&) and the left angle bracket (<) must not appear in their literal form (...) If they are needed elsewhere, they must be escaped using either numeric character references or the strings " &amp; " and " &lt; " respectively. The right angle bracket (>) may be represented using the string " &gt; " (...)

To allow attribute values to contain both single and double quotes, the apostrophe or single-quote character (') may be represented as " &apos; ", and the double-quote character (") as " &quot; ".

You can verify this easily by using createTextNode() to perform the correct escaping:

$dom = new DOMDocument;
$e = $dom->createElement('description');
$content = 'single quote: ', double quote: ", opening tag: <, ampersand: &, closing tag: >';
$t = $dom->createTextNode($content);
$e->appendChild($t);
$dom->appendChild($e);

echo $dom->saveXML();

Output:

<?xml version="1.0"?>
<description>single quote: ', double quote: ", opening tag: &lt;, ampersand: &amp;, closing tag: &gt;</description>
Saturday, May 29, 2021
 
nika
answered 5 Months ago
54

Based on your $_SESSION comment to Mike C,

foreach( $outer_array as $outer_key => $inner_array ) 
{
   foreach( $inner_array as $key => $value ) 
   {
      $_SESSION[$outer_key.'-'.$key] = $value;
   }
}

You would need unique keys though or (for instance) 'BCD118' and 'ABC' would both be key 0 and so 'ABC' would be overwritten.

Edit You could append the $outer_key to the inner $key to get a unique $_SESSION key

This would produce key/value pairs

0-0 : ABC
0-1 : 1
0-2 : 2
1-0 : BCD118
1-1 : 1
2-2 : 9
Saturday, May 29, 2021
 
VitaCoco
answered 5 Months ago
50

You can use File#isDirectory() to test if the given file (path) is a directory. If this is true, then you just call the same method again with its File#listFiles() outcome. This is called recursion.

Here's a basic kickoff example:

package com.stackoverflow.q3154488;

import java.io.File;

public class Demo {

    public static void main(String... args) {
        File dir = new File("/path/to/dir");
        showFiles(dir.listFiles());
    }

    public static void showFiles(File[] files) {
        for (File file : files) {
            if (file.isDirectory()) {
                System.out.println("Directory: " + file.getAbsolutePath());
                showFiles(file.listFiles()); // Calls same method again.
            } else {
                System.out.println("File: " + file.getAbsolutePath());
            }
        }
    }
}

Note that this is sensitive to StackOverflowError when the tree is deeper than the JVM's stack can hold. If you're already on Java 8 or newer, then you'd better use Files#walk() instead which utilizes tail recursion:

package com.stackoverflow.q3154488;

import java.io.File;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

public class DemoWithJava8 {

    public static void main(String... args) throws Exception {
        Path dir = Paths.get("/path/to/dir");
        Files.walk(dir).forEach(path -> showFile(path.toFile()));
    }

    public static void showFile(File file) {
        if (file.isDirectory()) {
            System.out.println("Directory: " + file.getAbsolutePath());
        } else {
            System.out.println("File: " + file.getAbsolutePath());
        }
    }
}
Tuesday, June 1, 2021
 
Angolao
answered 5 Months ago
21

You need to import any node to append it to another document:

$departmentArray->item($i)->appendChild( $doc->importNode( $employee, true ) );
Friday, August 6, 2021
 
previous_developer
answered 3 Months ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :