Hi Vishesh,

thanks a lot for the patch.
I would gladly include it in Soprano but there is one problem:
sopranocmd already has N3 parsing which is a bit more complex than your
version. It for example also includes prefix expansion. I already
started on a patch to convert that into a method of Node. The problem is
that I am not sure about the API yet.
Would you be interested to compare our patches? Maybe you have a good
idea on how to solve the problems I am facing: I am not too happy about
the error pointer parameter and the way the prefixes can be specified. I
already thought of maybe even creating a NodeParser class but then again
that seems a bit over the top...

Cheers,
Sebastian

On 03/24/2010 09:08 PM, Vishesh Handa wrote:
> Hi
> 
> I created a new function *static Node createFromN3( const QString& n3
> )*. It creates a Soprano::Node from an N3 String. I've /tried /to
> document it in the header file, but I'm not too sure if it's correct
> (the documentation). It would be nice if somebody could go through it,
> please.
> 
> The Patch had a base directory of /kdesupport/soprano/soprano/
> /
> - Vishesh Handa
> 
> 
> 
> _______________________________________________
> Nepomuk mailing list
> [email protected]
> https://mail.kde.org/mailman/listinfo/nepomuk
Index: node.h
===================================================================
--- node.h      (revision 1101894)
+++ node.h      (working copy)
@@ -26,6 +26,8 @@
 #include <QtCore/QUrl>
 #include <QtCore/QSharedDataPointer>
 #include <QtCore/QTextStream>
+#include <QtCore/QHash>
+#include <QtCore/QString>
 
 #include "soprano_export.h"
 #include "literalvalue.h"
@@ -34,6 +36,10 @@
 
 namespace Soprano
 {
+    namespace Error {
+        class Error;
+    }
+
     /**
      * \class Node node.h Soprano/Node
      *
@@ -429,12 +435,31 @@
          * "09-08-1977T17:42.234Z"^^<http://www.w3.org/2001/XMLSchema#dateTime>
          * \endcode
          *
-         * \sa toN3
+         * \sa toN3(), fromN3()
          *
          * \since 2.3
          */
         static QString literalToN3( const LiteralValue& literal );
 
+        /**
+         * Convert a node from its N3 representation.
+         *
+         * \param n3 The N3 representation of the node. \p true and \p false 
are treated as boolean
+         * literals, any string that can be parsed into a number is treated as 
integer or double
+         * literal, while any other string that is not a resource, blank node, 
or typed literal
+         * is treated as a plain literal.
+         * \param bnames An optional map of namespace abbreviations that could 
be used in \p n3.
+         * \param error An optional Error which will be filled in case parsing 
\p b3 fails.
+         *
+         * \return A %Node representing the parsed version of \p n3 or an 
invalid %Node in case
+         * parsing failed. In the latter case \p error will be filled with 
parsing error details.
+         *
+         * \sa resourceToN3(), literalToN3(), blankToN3(), toN3()
+         *
+         * \since 2.4
+         */
+        static Node fromN3( const QString& n3, /*const QHash<QString, QUrl>& 
bnames = QHash<QString, QUrl>(), */Error::Error* error = 0 );
+
     private:
         class NodeData;
         class ResourceNodeData;
Index: node.cpp
===================================================================
--- node.cpp    (revision 1101894)
+++ node.cpp    (working copy)
@@ -21,10 +21,14 @@
  */
 
 #include "node.h"
+#include "error.h"
+#include "locator.h"
+#include "vocabulary/rdf.h"
 
 #include <QtCore/QString>
 #include <QtCore/QUrl>
 #include <QtCore/QDebug>
+#include <QtCore/QRegExp>
 
 
 
@@ -425,6 +439,102 @@
 }
 
 
+namespace {
+    // FIXME: use QRegExp for all parsing.
+    // FIXME: Create a private NodeParser class which can also find the end of 
an n3 encoded node so we can reuse it
+    //        in the NQuadParser.
+    QRegExp s_prefixedUriRx( "(\\w+)\\:(\\w+)" );
+//     QRegExp s_typedLiteral1Rx( "^\"\"\"[^\"]+\"\"\"\\^\\^.+$" );
+//     QRegExp s_typedLiteral2Rx( "^\"[^\"]+\"\\^\\^.+$" );
+
+    QUrl parseUri( const QString& s ) {
+        // try to be a little smart about user input
+        if ( s.contains( '%' ) ) {
+            QByteArray b = s.toAscii();
+            if ( !b.isEmpty() ) {
+                return QUrl::fromEncoded( b );
+            }
+        }
+        return QUrl( s );
+    }
+}
+
+// static
+Soprano::Node Soprano::Node::fromN3( const QString& s, /*const QHash<QString, 
QUrl>& bnames, */Error::Error* error )
+{
+    // FIXME: put this in the parameters or for advanced users in a dedicated 
NodeParser class
+    QHash<QString, QUrl> bnames;
+
+    if ( s.isEmpty() ) {
+        return Soprano::Node();
+    }
+    else if ( s[0] == '<' && s[s.length()-1] == '>' ) {
+        return Soprano::Node( parseUri( s.mid( 1, s.length()-2 ) ) );
+    }
+    else if ( s[0] == '_' && s.length() > 2 && s[1] == ':' ) {
+        return Soprano::Node::createBlankNode( s.mid( 2 ) );
+    }
+    // FIXME: also handle """ as delimiters
+    else if ( s[0] == '"' ) {
+        QString value = s;
+        QString literalType;
+        int pos = s.indexOf( "\"^^<" );
+        if ( pos > 0 ) {
+            literalType = s.mid( pos + 4, s.length() - pos - 5 );
+            value = s.mid( 1, pos-1 );
+            return Soprano::LiteralValue::fromString( value, QUrl( literalType 
) );
+        }
+        else {
+            QString lang;
+            pos = s.indexOf( "\"@" );
+            int len = s.length()-2;
+            if ( pos > 0 ) {
+                lang = s.mid( pos+2, s.length() - pos - 2 );
+                len -= lang.length() + 1;
+            }
+            value = s.mid( 1, len );
+            return Soprano::LiteralValue::createPlainLiteral( value, lang );
+        }
+    }
+    else if ( s_prefixedUriRx.exactMatch( s ) ) {
+        const QString bname = s_prefixedUriRx.cap( 1 );
+        QUrl ns = bnames[bname];
+        if ( ns.isValid() ) {
+            return QUrl( ns.toString() + s_prefixedUriRx.cap( 2 ) );
+        }
+        else {
+            if( error ) {
+                *error = Error::ParserError( Error::Locator( 0, 0 ), 
QString::fromLatin1("Unknown namespace '%1'.").arg(bname) );
+            }
+            return Soprano::Node();
+        }
+    }
+    else if ( s == QLatin1String( "a" ) ) {
+        return Soprano::Vocabulary::RDF::type();
+    }
+    else {
+        // we only check for boolean, integer and double here
+        if ( s.toLower() == "false" )
+            return Soprano::LiteralValue( false );
+        else if ( s.toLower() == "true" )
+            return Soprano::LiteralValue( true );
+
+        bool ok = false;
+        int val = s.toInt( &ok );
+        if ( ok ) {
+            return Soprano::LiteralValue( val );
+        }
+        double dVal = s.toDouble( &ok );
+        if ( ok ) {
+            return Soprano::LiteralValue( dVal );
+        }
+        else {
+            return LiteralValue::createPlainLiteral( s );
+        }
+    }
+}
+
+
 QDebug operator<<( QDebug s, const Soprano::Node& n )
 {
     switch( n.type() ) {
_______________________________________________
Nepomuk mailing list
[email protected]
https://mail.kde.org/mailman/listinfo/nepomuk

Reply via email to