简体   繁体   中英

Search with PHP in XML <B> Data via <C> tag

First, i know that there are already some questions aubout similar things ( Searching an XML file using PHP Load external xml file? ), but i CAN'T make ANY PHP, so the following (search.php) is what I copy-pasted in PHP:

<html>
<head>
    <title>Search</title>
</head>
<body>
    <?php
    $search = $_POST["search"];
    $xml=simplexml_load_file("inhaltsverzeichniss.xml") or die("Error: Cannot create object");

    $result = $xml->xpath('//array/entry/tags[.="$search"]');

    while(list( , $node) = each($result)) {
        echo '/array/entry/tags: ',$node,"\n";
    }
    ?>
</body>

Then this is my HTML code (in case someone needs it):

<form action="search.php" method="post" >
    <input type="text" name="search" placeholder="search for stuff" >
    <input type="submit" name="search_button" value="Suche" >
</form>

and this is the XML Document I want to search in (inhaltsverzichniss.xml):

<?xml version="1.0" encoding="UTF-8"?>
<array>
  <entry>
    <url>Zeitformen Spanisch.odp</url>
    <name>Zeitformen Tabelle</name>
    <tags>spanisch</tags>
  </entry>
  <entry>
    <url>german-stuff.odt</url>
    <name>etwas Deutsches</name>
    <tags>german</tags>
  </entry>
  <entry>
    <url>something_english.html</url>
    <name>english things</name>
    <tags>english</tags>
  </entry>
  <entry>
    <url>other-data.fileextension</url>
    <name>cool name</name>
    <tags>etc.</tags>
  </entry>
</array>

What I want to do is search for tags written in the search form, and give the whole corresponding entry out. (like following: <a href"$url">$name</a><br>Tags: $tags )

EDIT: this is my current XML with entries with multiple tags (changed it to "tag"):

<array>
  <entry>
    <url>spanisch/Zeitformen_Spanisch.ods</url>
    <name>Zeitformen Tabelle</name>
    <tag>spanisch</tag>
  </entry>
  <entry>
    <url>german-stuff.odt</url>
    <name>etwas Deutsches</name>
    <tag>deutsch</tag>
    <tag>spanisch</tag>
    <tag>englisch</tag>
  </entry>
  <entry>
    <url>something_english.html</url>
    <name>english things</name>
    <tag>spanisch</tag>
    <tag>englisch</tag>
  </entry>
  <entry>
    <url>other-data.fileextension</url>
    <name>cool name</name>
    <tag>etc.</tag>
  </entry>
</array>

Quoting the PHP Manual:

Note: Unlike the double-quoted and heredoc syntaxes, variables and escape sequences for special characters will not be expanded when they occur in single quoted strings.

You are using single quotes in

$result = $xml->xpath('//array/entry/tags[.="$search"]');

but single quotes will treat the string content as literal strings. It won't interpolate $search like you think it does.

Change your code to

$result = $xml->xpath("//array/entry/tags[.='$search']");

and it will use the value of $search instead of the literal string "$search" .

However, since you want to print the full entry element, it would be better to use this XPath

$result = $xml->xpath("/array/entry[tags='$search']");

For readability I prefer

$result = $xml->xpath(sprintf('/array/entry[tags="%s"]', $search));

This will give you all the <entry> elements, instead of the <tags> elements in the $result . And while //array with a double slash does work, it's unneeded and performs somewhat worse than the direct path. That's because it will try to find the nodes regardless of position in the document.

You can then print it like you asked for like this:

foreach ($result as $entry) {
    printf(
        '<a href="%s">%s</a><br>Tags: %s%s',
        urlencode($entry->url),
        htmlspecialchars($entry->name),
        htmlspecialchars($entry->tags),
        PHP_EOL
    );
}

Regarding your edit with multiple tag elements:

The XPath above will already find the correct entries. To display all tags, you can change the line

htmlspecialchars($entry->tags),

to (don't forget to adjust the xpath to read tag instead of tags):

implode_tags($entry->tag),

with the implode_tags function being defined as

function implode_tags(\SimpleXMLElement $tags) {
    $allTags = [];
    foreach ($tags as $tag) {
        $allTags[] = htmlspecialchars($tag);
    }
    return implode(", ", $allTags);
}

This should then return something like "deutsch, spanisch, englisch"

See full demo at https://eval.in/885485

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM