Question

I'm programming a chatbot program on perl using an xml file which contains the patterns with each answers i m putting a pattern here for example, if the user introduces a string that contains the pattern "you know michael jordan", one of the possibls answers should be "who is michael jordan ?". the xml code is given below.

the problem is, i don't know how to extract the second part of the string introduced by the user, in the example given above "michael jordan" and put it in my output ??? and what do

<star/> and <star index="2"/> mean in XML ???

Thank you

<category> 
<pattern>you know *</pattern>
  <template> 
    <random> 
      <li>No, who is?</li>
      <li>who is <star/>?</li>
      <li>i don't know.</li>
    </random>
  </template>
</category>

the perl code :

my $parser  = XML::LibXML->new();
my $xmlfile = $parser->parse_file( $ARGV[0] );

my %palabras;
my @respuestas;

$xmlfile = $xmlfile->getDocumentElement();

my @kids = $xmlfile->findnodes('//category');

foreach my $child (@kids) {
    my $pattern = $child->findvalue('pattern');

    @respuestas = $child->findnodes('template/random/li');

    for my $answer (@respuestas) {
        push @{ $palabras{$pattern} }, $answer->textContent;
    }

}

my $cadena = <STDIN>;

while ( $cadena ne "adios\n" ) {
    foreach my $pattern ( keys %palabras ) {
        if ( index( uc $cadena, $pattern ) != -1 ) {
            @respuestas = @{ $palabras{$pattern} };
            my $n = int rand( $#respuestas + 1 );
            print $respuestas[$n] . "\n";    #
            last;
        }
    }

    $cadena = <STDIN>;
}
Was it helpful?

Solution

and what do <star/> and <star index="2"/> mean in XML ?

According to the XML spec section 3.1 , the grammar rule [44] describes "Tags for Empty Elements" which means, the element might have some attributes, but it has no content(in other words, no descendants, no text).

UPDATE

After reading more comments from OP and after some new updates on the question, here's one possible solution:

test.pl

#!/usr/bin/env perl
package Bot::Find::Answer;
use strict;
use warnings;
use XML::LibXML;
use Data::Dumper;
use List::Util qw/first/;

#### Constructor
#### Get path to XML with question/answer data.
#### Calls init to process data.
#### Returns new instance of object Bot::Find::Answer
sub new {
    my ($class,$xml_path) = @_;
    my $obj = bless {
        #### Path on disk to XML
        xml_path => $xml_path,
        #### Knowlege Base
        kb       => [],
    }, $class;
    $obj->init();
    return $obj;
};

#### Parse XML
#### Get stars in question and replace them with regex capture groups
#### Get all answers for each question and store them.
#### Store everything in $self->{kb}
sub init {
    my ($self) = @_;

    my $kb = $self->{kb};

    my $xml = XML::LibXML->load_xml(
        location => $self->{xml_path}
    );

    for my $cat ($xml->findnodes('//category')) {
        my $question_pattern = ($cat->findnodes('pattern'))[0]->textContent;
        $question_pattern =~ s/\*/(.*)/g;
        my @answers = 
        map { $_->textContent }
        $cat->findnodes('template/random/li');

        push @$kb, {
            p => $question_pattern,
            a => \@answers
        };
    };

};


#### Get first category for which the question matches the associated pattern
#### Pick a random answer
#### Fill random answer with captures from pattern.
#### Return answer
sub compute_answer {
    my ($self,$q) = @_;
    my $kb = $self->{kb};
    my $cat_found = first { $q =~ /$_->{p}/ } @$kb;
    my $idx = int(rand(@{ $cat_found->{a}}));
    my $picked_answer = $cat_found->{a}->[$idx];
    my (@captures) = $q =~ $cat_found->{p};
    for my $i (0..(-1+@captures)) {
        my $j = $i + 1;
        my $capture_val = $captures[$i];
        $picked_answer =~ s/\[capture$j\]/$capture_val/g;
    };

    return $picked_answer;
}

package main;

my $o = Bot::Find::Answer->new('sample.xml');
print $o->compute_answer("you know michael jordan");

sample.xml:

<?xml version="1.0" encoding="iso-8859-1"?>
<data>
    <category> 
        <pattern>you know *</pattern>
        <template> 
            <random> 
                <li>No, who is [capture1]?</li>
                <li>who is [capture1]?</li>
                <li>i don't know.</li>
            </random>
        </template>
    </category>
    <category> 
        <pattern>name a country from south america</pattern>
        <template> 
            <random> 
                <li>ecuador</li>
                <li>uruguay</li>
                <li>chile</li>
                <li>panama</li>
                <li>brazil</li>
            </random>
        </template>
    </category>
</data>
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top