Hi Henry,
Thanks for your feedback!

>I wonder if the following could make it even simpler though:
First I think, why not make the currency a literal?

foo:offering a gr:Offering;
    rdfs:label "Volkswagen Station Wagon, 4WD, 400 $"@en;
    rdfs:description "I sell my old Volkswagen Station Wagon, 4WD, for 400 
$"@en;
    gr:hasPriceSpecification
        [ a gr:UnitPriceSpecification;
            gr:value "400"^^gr:USD;
        ] .

When you have a relation from a string to a value, you have a literal. monetary 
values are good
examples it seems to me of this. It would remove at least three of your URL 
usages, as you had
to specify the xsd:string twice, and also the type of the currency.
There are several reasons for using the current GoodRelations pattern. The most important one is that GoodRelations represents all point values internally as intervals, in order to support reasoning over ranges with simple RDFS-style reasoners. As for prices, that has been an explicit request from the hotel domain.

So gr:hasCurrencyValue is an rdfs:subPropertyOf gr:hasMaxCurrencyValue AND of gr:hasMinCurrencyValue. This gives a nice coherent model for point values and intervals, without the need for a SPARQL endpoint and either a bit of RDFS-style reasoning or a bit of SPARQL query expansion.

Example:
# 3..4 USD per kilogram, e.g. depending on the size of the potatoes
foo:price a gr:UnitPriceSpecification ;
    gr:hasCurrency "USD"^^xsd:string ;
    gr:hasMinCurrencyValue "3.0"^^xsd:float ;
    gr:hasMaxCurrencyValue "4.0"^^xsd:float ;
    gr:hasUnitOfMeasurement "KGM"^^xsd:string ;
    gr:valueAddedTaxIncluded "true"^^xsd:boolean .

# 4 USD per kilogram
foo:price a gr:UnitPriceSpecification ;
    gr:hasCurrency "USD"^^xsd:string ;
    gr:hasCurrencyValue "4.0"^^xsd:float ;
    gr:hasUnitOfMeasurement "KGM"^^xsd:string ;
    gr:valueAddedTaxIncluded "true"^^xsd:boolean .

Both will work with the following query:

# find something that has a price or upper price limit of less than 4 USD / kg

SELECT ?offer WHERE
{
?offer a gr:Offering .
?offer gr:hasPriceSpecification ?p .
?p gr:hasMaxCurrencyValue ?v .
?p gr:hasCurrency "USD"^^xsd:string .
?p gr:UnitOfMeasurement "KGM"^^xsd:string .
FILTER (?p <= "4")
}

The important message is that, without any domain-specific tweak of the GoodRelations vocabulary, you can model things as simple as this

foo:offering a gr:Offering;
    rdfs:label "Volkswagen Station Wagon, 4WD, 400 $"@en;
rdfs:comment "I sell my old Volkswagen Station Wagon, 4WD, for 400 $"@en;
    gr:hasBusinessFunction gr:Sell;
    gr:hasPriceSpecification
        [ a gr:UnitPriceSpecification;
            gr:hasCurrencyValue "400"^^xsd:float;
            gr:hasCurrency "USD"^^xsd:string. ].

and as fine-granular as this:

# Boat Rental: 24 USD / 6 hours for 0-3 days, 75 USD per day for any longer rental

foo:company a gr:BusinessEntity ;
    gr:legalName "Hepp Space Ventures, Inc."@en ;
    gr:offers foo:boat_offer.

foo:boat_offer a gr:Offering ;
    rdfs:label "Boat rental"@en ;
    rdfs:comment "We rent out boats"@en ;
    gr:hasBusinessFunction gr:LeaseOut ;
    gr:hasPriceSpecification foo:rental_price1, foo:rental_price2 .

foo:rental_price1 a gr:UnitPriceSpecification ;
    gr:hasCurrency "USD"^^xsd:string ;
    # 24 USD per 6 hours => 4 USD / hour
    gr:hasCurrencyValue "4"^^xsd:float ;
    gr:hasUnitOfMeasurement "HUR"^^xsd:string ;
    gr:billingIncrement "6"^^xsd:float
    gr:valueAddedTaxIncluded "true"^^xsd:boolean ;
    gr:hasEligibleQuantity [ a gr:QuantitativeValueInteger ;
                            gr:hasUnitOfMeasurement "DAY"^^xsd:string ;
                            gr:hasMinValueInteger "0"^^xsd:int ;
                            gr:hasMaxValueInteger "3"^^xsd:int . ].

foo:rental_price2 a gr:UnitPriceSpecification ;
    gr:hasCurrency "USD"^^xsd:string ;
    gr:hasCurrencyValue "75"^^xsd:float ;
    gr:hasUnitOfMeasurement "DAY"^^xsd:string ;
    gr:valueAddedTaxIncluded "true"^^xsd:boolean ;
    gr:hasEligibleQuantity [ a gr:QuantitativeValueInteger ;
                            gr:hasUnitOfMeasurement "DAY"^^xsd:string ;
                            gr:hasMinValueInteger "4"^^xsd:int . ].

And both use the same set of conceptual elements, and will basically trigger the very same SPARQL queries. That is a major difference to any other conceptual approach for product / offer data on the Web - to keep the simple things simple while supporting the very complex cases off the box.

Also in your example you could put the company in a different file, and refer 
to it by
reference.
Yes, I agree. In particular, in RDFa one will use the rev attribute to do that.


Best

Martin


--
--------------------------------------------------------------
martin hepp
e-business&  web science research group
universitaet der bundeswehr muenchen

e-mail:h...@ebusiness-unibw.org
phone:   +49-(0)89-6004-4217
fax:     +49-(0)89-6004-4620
www:http://www.unibw.de/ebusiness/  (group)
         http://www.heppnetz.de/  (personal)
skype:   mfhepp
twitter: mfhepp

Check out GoodRelations for E-Commerce on the Web of Linked Data!
=================================================================

Project page:
http://purl.org/goodrelations/

Resources for developers:
http://www.ebusiness-unibw.org/wiki/GoodRelations

Webcasts:
Overview -http://www.heppnetz.de/projects/goodrelations/webcast/
How-to   -http://vimeo.com/7583816

Recipe for Yahoo SearchMonkey:
http://www.ebusiness-unibw.org/wiki/GoodRelations_and_Yahoo_SearchMonkey

Talk at the Semantic Technology Conference 2009:
"Semantic Web-based E-Commerce: The GoodRelations Ontology"
http://www.slideshare.net/mhepp/semantic-webbased-ecommerce-the-goodrelations-ontology-1535287

Overview article on Semantic Universe:
http://www.semanticuniverse.com/articles-semantic-web-based-e-commerce-webmasters-get-ready.html

Tutorial materials:
ISWC 2009 Tutorial: The Web of Data for E-Commerce in Brief: A Hands-on 
Introduction to the GoodRelations Ontology, RDFa, and Yahoo! SearchMonkey
http://www.ebusiness-unibw.org/wiki/Web_of_Data_for_E-Commerce_Tutorial_ISWC2009


Reply via email to