/// <summary> /// Finds if the given token contains a recognizable namespace and, if so, abbreviates it with its prefix. /// It also prepares the result in a format useful for serialization. /// </summary> internal static String AbbreviateNamespace(String token) { //Null or Space token: it's a trick, give empty result if (token == null || token.Trim() == String.Empty) { return String.Empty; } //Blank token: abbreviate it with "_" if (token.StartsWith("bnode:")) { return token.Replace("bnode:", "_:"); } //Prefixed token: check if it starts with a known prefix, if so just return it if (RDFNamespaceRegister.GetByPrefix(token.Split(':')[0]) != null) { return token; } //Uri token: search a known namespace, if found replace it with its prefix String tokenBackup = token; Boolean abbrev = false; RDFNamespaceRegister.Instance.Register.ForEach(ns => { if (!abbrev) { String nS = ns.ToString(); if (!token.Equals(nS, StringComparison.OrdinalIgnoreCase)) { if (token.StartsWith(nS)) { token = token.Replace(nS, ns.NamespacePrefix + ":").TrimEnd(new Char[] { '/' }); //Accept the abbreviation only if it has generated a valid XSD QName try { var qn = new RDFTypedLiteral(token, RDFModelEnums.RDFDatatypes.XSD_QNAME); abbrev = true; } catch { token = tokenBackup; abbrev = false; } } } } }); //Search done, let's analyze results: if (abbrev) { return token; //token is a relative or a blank uri } if (token.Contains("^^")) { //token is a typedLiteral absolute uri return token.Replace("^^", "^^<") + ">"; } return "<" + token + ">"; //token is an absolute uri }
/// <summary> /// Parses the current quadruple of the data reader /// </summary> public static RDFQuadruple ParseQuadruple(IDataReader fetchedQuadruples) { if (fetchedQuadruples != null) { RDFContext qContext = new RDFContext(fetchedQuadruples["Context"].ToString()); RDFResource qSubject = new RDFResource(fetchedQuadruples["Subject"].ToString()); RDFResource qPredicate = new RDFResource(fetchedQuadruples["Predicate"].ToString()); //SPO-flavour quadruple if (fetchedQuadruples["TripleFlavor"].ToString() == "1") { RDFResource qObject = new RDFResource(fetchedQuadruples["Object"].ToString()); return new RDFQuadruple(qContext, qSubject, qPredicate, qObject); } //SPL-flavour quadruple String literal = fetchedQuadruples["Object"].ToString(); //PlainLiteral if (!literal.Contains("^^") || literal.EndsWith("^^") || RDFModelUtilities.GetUriFromString(literal.Substring(literal.LastIndexOf("^^", StringComparison.Ordinal) + 2)) == null) { RDFPlainLiteral pLit = null; if (literal.Contains("@")) { if (!literal.EndsWith("@")) { Int32 lastAmp = literal.LastIndexOf('@'); pLit = new RDFPlainLiteral(literal.Substring(0, lastAmp), literal.Substring(lastAmp + 1)); } else { pLit = new RDFPlainLiteral(literal); } } else { pLit = new RDFPlainLiteral(literal); } return new RDFQuadruple(qContext, qSubject, qPredicate, pLit); } //TypedLiteral String tLitValue = literal.Substring(0, literal.LastIndexOf("^^", StringComparison.Ordinal)); String tLitDatatype = literal.Substring(literal.LastIndexOf("^^", StringComparison.Ordinal) + 2); RDFDatatype dt = RDFModelUtilities.GetDatatypeFromString(tLitDatatype); RDFTypedLiteral tLit = new RDFTypedLiteral(tLitValue, dt); return new RDFQuadruple(qContext, qSubject, qPredicate, tLit); } throw new RDFStoreException("Cannot parse quadruple because given \"fetchedQuadruples\" parameter is null."); }
/// <summary> /// Parses the given string to return an instance of pattern member /// </summary> internal static RDFPatternMember ParseRDFPatternMember(String pMember) { if (pMember != null) { #region Uri Uri testUri; if (Uri.TryCreate(pMember, UriKind.Absolute, out testUri)) { return new RDFResource(pMember); } #endregion #region Plain Literal if (!pMember.Contains("^^") || pMember.EndsWith("^^") || RDFModelUtilities.GetUriFromString(pMember.Substring(pMember.LastIndexOf("^^", StringComparison.Ordinal) + 2)) == null) { RDFPlainLiteral pLit = null; if (RDFNTriples.regexLPL.Match(pMember).Success) { String pLitVal = pMember.Substring(0, pMember.LastIndexOf("@", StringComparison.Ordinal)); String pLitLng = pMember.Substring(pMember.LastIndexOf("@", StringComparison.Ordinal) + 1); pLit = new RDFPlainLiteral(pLitVal, pLitLng); } else { pLit = new RDFPlainLiteral(pMember); } return pLit; } #endregion #region Typed Literal String tLitValue = pMember.Substring(0, pMember.LastIndexOf("^^", StringComparison.Ordinal)); String tLitDatatype = pMember.Substring(pMember.LastIndexOf("^^", StringComparison.Ordinal) + 2); RDFModelEnums.RDFDatatypes dt = RDFModelUtilities.GetDatatypeFromString(tLitDatatype); RDFTypedLiteral tLit = new RDFTypedLiteral(tLitValue, dt); return tLit; #endregion } throw new RDFQueryException("Cannot parse pattern member because given \"pMember\" parameter is null."); }
/// <summary> /// Parses the given string to return an instance of pattern member /// </summary> public static RDFPatternMember ParseRDFPatternMember(String pMember) { if (pMember != null) { #region Uri Uri testUri; if (Uri.TryCreate(pMember, UriKind.Absolute, out testUri)) { return new RDFResource(pMember); } #endregion #region Plain Literal if (!pMember.Contains("^^") || pMember.EndsWith("^^") || RDFModelUtilities.GetUriFromString(pMember.Substring(pMember.LastIndexOf("^^", StringComparison.Ordinal) + 2)) == null) { RDFPlainLiteral pLit = null; if (pMember.Contains("@")) { if (!pMember.EndsWith("@")) { Int32 lastAmp = pMember.LastIndexOf('@'); pLit = new RDFPlainLiteral(pMember.Substring(0, lastAmp), pMember.Substring(lastAmp + 1)); } else { pLit = new RDFPlainLiteral(pMember); } } else { pLit = new RDFPlainLiteral(pMember); } return pLit; } #endregion #region Typed Literal String tLitValue = pMember.Substring(0, pMember.LastIndexOf("^^", StringComparison.Ordinal)); String tLitDatatype = pMember.Substring(pMember.LastIndexOf("^^", StringComparison.Ordinal) + 2); RDFDatatype dt = RDFModelUtilities.GetDatatypeFromString(tLitDatatype); RDFTypedLiteral tLit = new RDFTypedLiteral(tLitValue, dt); return tLit; #endregion } throw new RDFQueryException("Cannot parse pattern member because given \"pMember\" parameter is null."); }
/// <summary> /// Deserializes the given N-Triples stream to a graph. /// </summary> internal static RDFGraph Deserialize(Stream inputStream) { Int64 ntripleIndex = 0; try { #region deserialize using (StreamReader sr = new StreamReader(inputStream, Encoding.ASCII)) { RDFGraph result = new RDFGraph(); String ntriple = String.Empty; String[] tokens = new String[3]; RDFResource S = null; RDFResource P = null; RDFResource O = null; RDFLiteral L = null; while ((ntriple = sr.ReadLine()) != null) { ntripleIndex++; #region sanitize & tokenize //Cleanup previous data S = null; tokens[0] = String.Empty; P = null; tokens[1] = String.Empty; O = null; L = null; tokens[2] = String.Empty; //Preliminary sanitizations: clean trailing space-like chars ntriple = ntriple.Trim(new Char[] { ' ', '\t', '\r', '\n' }); //Skip empty or comment lines if (ntriple == String.Empty || ntriple.StartsWith("#")) { continue; } //Tokenizes the sanitized triple tokens = TokenizeNTriple(ntriple); #endregion #region subj String subj = tokens[0].TrimStart(new Char[] { '<' }) .TrimEnd(new Char[] { '>' }) .Replace("_:", "bnode:"); S = new RDFResource(RDFModelUtilities.ASCII_To_Unicode(subj)); #endregion #region pred String pred = tokens[1].TrimStart(new Char[] { '<' }) .TrimEnd(new Char[] { '>' }); P = new RDFResource(RDFModelUtilities.ASCII_To_Unicode(pred)); #endregion #region object if (tokens[2].StartsWith("<") || tokens[2].StartsWith("bnode:") || tokens[2].StartsWith("_:")) { String obj = tokens[2].TrimStart(new Char[] { '<' }) .TrimEnd(new Char[] { '>' }) .Replace("_:", "bnode:") .Trim(new Char[] { ' ', '\n', '\t', '\r' }); O = new RDFResource(RDFModelUtilities.ASCII_To_Unicode(obj)); } #endregion #region literal else { #region sanitize tokens[2] = regexSqt.Replace(tokens[2], String.Empty); tokens[2] = regexEqt.Replace(tokens[2], String.Empty); tokens[2] = tokens[2].Replace("\\\\", "\\") .Replace("\\\"", "\"") .Replace("\\n", "\n") .Replace("\\t", "\t") .Replace("\\r", "\r"); tokens[2] = RDFModelUtilities.ASCII_To_Unicode(tokens[2]); #endregion #region plain literal if (!tokens[2].Contains("^^") || tokens[2].EndsWith("^^") || tokens[2].Substring(tokens[2].LastIndexOf("^^", StringComparison.Ordinal) + 2, 1) != "<") { if (regexLPL.Match(tokens[2]).Success) { tokens[2] = tokens[2].Replace("\"@", "@"); String pLitValue = tokens[2].Substring(0, tokens[2].LastIndexOf("@", StringComparison.Ordinal)); String pLitLang = tokens[2].Substring(tokens[2].LastIndexOf("@", StringComparison.Ordinal) + 1); L = new RDFPlainLiteral(HttpUtility.HtmlDecode(pLitValue), pLitLang); } else { L = new RDFPlainLiteral(HttpUtility.HtmlDecode(tokens[2])); } } #endregion #region typed literal else { tokens[2] = tokens[2].Replace("\"^^", "^^"); String tLitValue = tokens[2].Substring(0, tokens[2].LastIndexOf("^^", StringComparison.Ordinal)); String tLitDatatype = tokens[2].Substring(tokens[2].LastIndexOf("^^", StringComparison.Ordinal) + 2) .TrimStart(new Char[] { '<' }) .TrimEnd(new Char[] { '>' }); RDFModelEnums.RDFDatatypes dt = RDFModelUtilities.GetDatatypeFromString(tLitDatatype); L = new RDFTypedLiteral(HttpUtility.HtmlDecode(tLitValue), dt); } #endregion } #endregion #region addtriple if (O != null) { result.AddTriple(new RDFTriple(S, P, O)); } else { result.AddTriple(new RDFTriple(S, P, L)); } #endregion } return(result); } #endregion } catch (Exception ex) { throw new RDFModelException("Cannot deserialize N-Triples (line " + ntripleIndex + ") because: " + ex.Message, ex); } }
/// <summary> /// Validates the value of the given typed literal against the category of its datatype /// </summary> internal static Boolean ValidateTypedLiteral(RDFTypedLiteral typedLiteral) { if (typedLiteral != null) { Boolean validateResponse = true; switch (typedLiteral.Datatype.Category) { //STRING TYPES case RDFModelEnums.RDFDatatypeCategory.String: //ANYURI if (typedLiteral.Datatype.Equals(RDFDatatypeRegister.GetByPrefixAndDatatype(RDFVocabulary.XSD.PREFIX, "anyURI"))) { Uri outUri; if (!Uri.TryCreate(typedLiteral.Value, UriKind.Absolute, out outUri)) { validateResponse = false; } } //XML_LITERAL else if (typedLiteral.Datatype.Equals(RDFDatatypeRegister.GetByPrefixAndDatatype(RDFVocabulary.RDF.PREFIX, "XMLLiteral"))) { try { XDocument.Parse(typedLiteral.Value); } catch { validateResponse = false; } } //NAME else if (typedLiteral.Datatype.Equals(RDFDatatypeRegister.GetByPrefixAndDatatype(RDFVocabulary.XSD.PREFIX, "Name"))) { try { XmlConvert.VerifyName(typedLiteral.Value); } catch { validateResponse = false; } } //NCNAME else if (typedLiteral.Datatype.Equals(RDFDatatypeRegister.GetByPrefixAndDatatype(RDFVocabulary.XSD.PREFIX, "NCName"))) { try { XmlConvert.VerifyNCName(typedLiteral.Value); } catch { validateResponse = false; } } //TOKEN else if (typedLiteral.Datatype.Equals(RDFDatatypeRegister.GetByPrefixAndDatatype(RDFVocabulary.XSD.PREFIX, "token"))) { try { XmlConvert.VerifyTOKEN(typedLiteral.Value); } catch { validateResponse = false; } } //NMTOKEN else if (typedLiteral.Datatype.Equals(RDFDatatypeRegister.GetByPrefixAndDatatype(RDFVocabulary.XSD.PREFIX, "NMToken"))) { try { XmlConvert.VerifyNMTOKEN(typedLiteral.Value); } catch { validateResponse = false; } } //NORMALIZED_STRING else if (typedLiteral.Datatype.Equals(RDFDatatypeRegister.GetByPrefixAndDatatype(RDFVocabulary.XSD.PREFIX, "normalizedString"))) { if (typedLiteral.Value.Contains('\r') || typedLiteral.Value.Contains('\n') || typedLiteral.Value.Contains('\t')) { validateResponse = false; } } //LANGUAGE else if (typedLiteral.Datatype.Equals(RDFDatatypeRegister.GetByPrefixAndDatatype(RDFVocabulary.XSD.PREFIX, "language"))) { if (!Regex.IsMatch(typedLiteral.Value, "^[a-zA-Z]+([\\-][a-zA-Z0-9]+)*$")) { validateResponse = false; } } //BASE64_BINARY else if (typedLiteral.Datatype.Equals(RDFDatatypeRegister.GetByPrefixAndDatatype(RDFVocabulary.XSD.PREFIX, "base64Binary"))) { try { Convert.FromBase64String(typedLiteral.Value); } catch { validateResponse = false; } } //HEX_BINARY else if (typedLiteral.Datatype.Equals(RDFDatatypeRegister.GetByPrefixAndDatatype(RDFVocabulary.XSD.PREFIX, "hexBinary"))) { if ((typedLiteral.Value.Length % 2 != 0) || (!Regex.IsMatch(typedLiteral.Value, @"^[a-fA-F0-9]+$"))) { validateResponse = false; } } break; //BOOLEAN TYPES case RDFModelEnums.RDFDatatypeCategory.Boolean: Boolean outBool; if (!Boolean.TryParse(typedLiteral.Value, out outBool)) { validateResponse = false; } break; //DATETIME TYPES case RDFModelEnums.RDFDatatypeCategory.DateTime: //DATETIME if (typedLiteral.Datatype.Equals(RDFDatatypeRegister.GetByPrefixAndDatatype(RDFVocabulary.XSD.PREFIX, "dateTime"))) { try { DateTime.ParseExact(typedLiteral.Value, "yyyy-MM-ddTHH:mm:ssK", CultureInfo.InvariantCulture); } catch { try { DateTime.ParseExact(typedLiteral.Value, "yyyy-MM-ddTHH:mm:ss", CultureInfo.InvariantCulture); } catch { validateResponse = false; } } } //DATE else if (typedLiteral.Datatype.Equals(RDFDatatypeRegister.GetByPrefixAndDatatype(RDFVocabulary.XSD.PREFIX, "date"))) { try { DateTime.ParseExact(typedLiteral.Value, "yyyy-MM-ddK", CultureInfo.InvariantCulture); } catch { try { DateTime.ParseExact(typedLiteral.Value, "yyyy-MM-dd", CultureInfo.InvariantCulture); } catch { validateResponse = false; } } } //TIME else if (typedLiteral.Datatype.Equals(RDFDatatypeRegister.GetByPrefixAndDatatype(RDFVocabulary.XSD.PREFIX, "time"))) { try { DateTime.ParseExact(typedLiteral.Value, "HH:mm:ssK", CultureInfo.InvariantCulture); } catch { try { DateTime.ParseExact(typedLiteral.Value, "HH:mm:ss", CultureInfo.InvariantCulture); } catch { validateResponse = false; } } } //G_MONTH_DAY else if (typedLiteral.Datatype.Equals(RDFDatatypeRegister.GetByPrefixAndDatatype(RDFVocabulary.XSD.PREFIX, "gMonthDay"))) { try { DateTime.ParseExact(typedLiteral.Value, "--MM-ddK", CultureInfo.InvariantCulture); } catch { try { DateTime.ParseExact(typedLiteral.Value, "--MM-dd", CultureInfo.InvariantCulture); } catch { validateResponse = false; } } } //G_YEAR_MONTH else if (typedLiteral.Datatype.Equals(RDFDatatypeRegister.GetByPrefixAndDatatype(RDFVocabulary.XSD.PREFIX, "gYearMonth"))) { try { DateTime.ParseExact(typedLiteral.Value, "yyyy-MMK", CultureInfo.InvariantCulture); } catch { try { DateTime.ParseExact(typedLiteral.Value, "yyyy-MM", CultureInfo.InvariantCulture); } catch { validateResponse = false; } } } //G_YEAR else if (typedLiteral.Datatype.Equals(RDFDatatypeRegister.GetByPrefixAndDatatype(RDFVocabulary.XSD.PREFIX, "gYear"))) { try { DateTime.ParseExact(typedLiteral.Value, "yyyyK", CultureInfo.InvariantCulture); } catch { try { DateTime.ParseExact(typedLiteral.Value, "yyyy", CultureInfo.InvariantCulture); } catch { validateResponse = false; } } } //G_MONTH else if (typedLiteral.Datatype.Equals(RDFDatatypeRegister.GetByPrefixAndDatatype(RDFVocabulary.XSD.PREFIX, "gMonth"))) { try { DateTime.ParseExact(typedLiteral.Value, "MMK", CultureInfo.InvariantCulture); } catch { try { DateTime.ParseExact(typedLiteral.Value, "MM", CultureInfo.InvariantCulture); } catch { validateResponse = false; } } } //G_DAY else if (typedLiteral.Datatype.Equals(RDFDatatypeRegister.GetByPrefixAndDatatype(RDFVocabulary.XSD.PREFIX, "gDay"))) { try { DateTime.ParseExact(typedLiteral.Value, "ddK", CultureInfo.InvariantCulture); } catch { try { DateTime.ParseExact(typedLiteral.Value, "dd", CultureInfo.InvariantCulture); } catch { validateResponse = false; } } } break; //TIMESPAN TYPES case RDFModelEnums.RDFDatatypeCategory.TimeSpan: try { XmlConvert.ToTimeSpan(typedLiteral.Value); } catch { validateResponse = false; } break; //NUMERIC TYPES case RDFModelEnums.RDFDatatypeCategory.Numeric: Decimal outDecimal; if (Decimal.TryParse(typedLiteral.Value, NumberStyles.Number, CultureInfo.InvariantCulture, out outDecimal)) { //INTEGER if (typedLiteral.Datatype.Equals(RDFDatatypeRegister.GetByPrefixAndDatatype(RDFVocabulary.XSD.PREFIX, "integer")) || typedLiteral.Datatype.Equals(RDFDatatypeRegister.GetByPrefixAndDatatype(RDFVocabulary.XSD.PREFIX, "int")) || typedLiteral.Datatype.Equals(RDFDatatypeRegister.GetByPrefixAndDatatype(RDFVocabulary.XSD.PREFIX, "positiveInteger")) || typedLiteral.Datatype.Equals(RDFDatatypeRegister.GetByPrefixAndDatatype(RDFVocabulary.XSD.PREFIX, "negativeInteger")) || typedLiteral.Datatype.Equals(RDFDatatypeRegister.GetByPrefixAndDatatype(RDFVocabulary.XSD.PREFIX, "nonPositiveInteger")) || typedLiteral.Datatype.Equals(RDFDatatypeRegister.GetByPrefixAndDatatype(RDFVocabulary.XSD.PREFIX, "nonNegativeInteger"))) { Int32 outInteger; if (Int32.TryParse(typedLiteral.Value, NumberStyles.Number, CultureInfo.InvariantCulture, out outInteger)) { //SUB-INTEGER if(typedLiteral.Datatype.Equals(RDFDatatypeRegister.GetByPrefixAndDatatype(RDFVocabulary.XSD.PREFIX, "positiveInteger")) || typedLiteral.Datatype.Equals(RDFDatatypeRegister.GetByPrefixAndDatatype(RDFVocabulary.XSD.PREFIX, "nonNegativeInteger"))) { if (outInteger < 0) { validateResponse = false; } } else if (typedLiteral.Datatype.Equals(RDFDatatypeRegister.GetByPrefixAndDatatype(RDFVocabulary.XSD.PREFIX, "negativeInteger")) || typedLiteral.Datatype.Equals(RDFDatatypeRegister.GetByPrefixAndDatatype(RDFVocabulary.XSD.PREFIX, "nonPositiveInteger"))) { if (outInteger >= 0) { validateResponse = false; } } } else { validateResponse = false; } } //LONG else if (typedLiteral.Datatype.Equals(RDFDatatypeRegister.GetByPrefixAndDatatype(RDFVocabulary.XSD.PREFIX, "long"))) { Int64 outlong; if (!Int64.TryParse(typedLiteral.Value, NumberStyles.Number, CultureInfo.InvariantCulture, out outlong)) { validateResponse = false; } } //SHORT else if (typedLiteral.Datatype.Equals(RDFDatatypeRegister.GetByPrefixAndDatatype(RDFVocabulary.XSD.PREFIX, "short"))) { Int16 outShort; if (!Int16.TryParse(typedLiteral.Value, NumberStyles.Number, CultureInfo.InvariantCulture, out outShort)) { validateResponse = false; } } //FLOAT else if (typedLiteral.Datatype.Equals(RDFDatatypeRegister.GetByPrefixAndDatatype(RDFVocabulary.XSD.PREFIX, "float"))) { Single outFloat; if (!Single.TryParse(typedLiteral.Value, NumberStyles.Number, CultureInfo.InvariantCulture, out outFloat)) { validateResponse = false; } } //DOUBLE else if (typedLiteral.Datatype.Equals(RDFDatatypeRegister.GetByPrefixAndDatatype(RDFVocabulary.XSD.PREFIX, "double"))) { Double outDouble; if (!Double.TryParse(typedLiteral.Value, NumberStyles.Number, CultureInfo.InvariantCulture, out outDouble)) { validateResponse = false; } } //BYTE else if (typedLiteral.Datatype.Equals(RDFDatatypeRegister.GetByPrefixAndDatatype(RDFVocabulary.XSD.PREFIX, "byte"))) { SByte outSByte; if (!SByte.TryParse(typedLiteral.Value, NumberStyles.Number, CultureInfo.InvariantCulture, out outSByte)) { validateResponse = false; } } //UNSIGNED TYPES else if (typedLiteral.Datatype.Equals(RDFDatatypeRegister.GetByPrefixAndDatatype(RDFVocabulary.XSD.PREFIX, "unsignedByte")) || typedLiteral.Datatype.Equals(RDFDatatypeRegister.GetByPrefixAndDatatype(RDFVocabulary.XSD.PREFIX, "unsignedShort")) || typedLiteral.Datatype.Equals(RDFDatatypeRegister.GetByPrefixAndDatatype(RDFVocabulary.XSD.PREFIX, "unsignedInt")) || typedLiteral.Datatype.Equals(RDFDatatypeRegister.GetByPrefixAndDatatype(RDFVocabulary.XSD.PREFIX, "unsignedLong"))) { //UNSIGNED BYTE if (typedLiteral.Datatype.Equals(RDFDatatypeRegister.GetByPrefixAndDatatype(RDFVocabulary.XSD.PREFIX, "unsignedByte"))) { Byte outByte; if (!Byte.TryParse(typedLiteral.Value, NumberStyles.Number, CultureInfo.InvariantCulture, out outByte)) { validateResponse = false; } } //UNSIGNED SHORT else if (typedLiteral.Datatype.Equals(RDFDatatypeRegister.GetByPrefixAndDatatype(RDFVocabulary.XSD.PREFIX, "unsignedShort"))) { UInt16 outUShort; if (!UInt16.TryParse(typedLiteral.Value, NumberStyles.Number, CultureInfo.InvariantCulture, out outUShort)) { validateResponse = false; } } //UNSIGNED INT else if (typedLiteral.Datatype.Equals(RDFDatatypeRegister.GetByPrefixAndDatatype(RDFVocabulary.XSD.PREFIX, "unsignedInt"))) { UInt32 outUInt; if (!UInt32.TryParse(typedLiteral.Value, NumberStyles.Number, CultureInfo.InvariantCulture, out outUInt)) { validateResponse = false; } } //UNSIGNED LONG else if (typedLiteral.Datatype.Equals(RDFDatatypeRegister.GetByPrefixAndDatatype(RDFVocabulary.XSD.PREFIX, "unsignedLong"))) { UInt64 outULong; if (!UInt64.TryParse(typedLiteral.Value, NumberStyles.Number, CultureInfo.InvariantCulture, out outULong)) { validateResponse = false; } } } } else { validateResponse = false; } break; } return validateResponse; } throw new RDFModelException("Cannot validate RDFTypedLiteral because given \"typedLiteral\" parameter is null."); }
/// <summary> /// Validates the value of the given typed literal against its datatype /// </summary> internal static Boolean ValidateTypedLiteral(RDFTypedLiteral typedLiteral) { if (typedLiteral != null) { #region STRING CATEGORY //LITERAL / STRING if (typedLiteral.Datatype.Equals(RDFModelEnums.RDFDatatypes.RDFS_LITERAL) || typedLiteral.Datatype.Equals(RDFModelEnums.RDFDatatypes.XSD_STRING)) { return true; } //XML_LITERAL if (typedLiteral.Datatype.Equals(RDFModelEnums.RDFDatatypes.RDF_XMLLITERAL)) { try { XDocument.Parse(typedLiteral.Value); return true; } catch { return false; } } //ANYURI if (typedLiteral.Datatype.Equals(RDFModelEnums.RDFDatatypes.XSD_ANYURI)) { Uri outUri; if (Uri.TryCreate(typedLiteral.Value, UriKind.Absolute, out outUri)) { typedLiteral.Value = Convert.ToString(outUri); return true; } return false; } //NAME if (typedLiteral.Datatype.Equals(RDFModelEnums.RDFDatatypes.XSD_NAME)) { try { XmlConvert.VerifyName(typedLiteral.Value); return true; } catch { return false; } } //QNAME if (typedLiteral.Datatype.Equals(RDFModelEnums.RDFDatatypes.XSD_QNAME)) { var prefixedQName = typedLiteral.Value.Split(':'); if (prefixedQName.Length == 1) { try { XmlConvert.VerifyNCName(prefixedQName[0]); return true; } catch { return false; } } else if(prefixedQName.Length == 2) { try { XmlConvert.VerifyNCName(prefixedQName[0]); XmlConvert.VerifyNCName(prefixedQName[1]); return true; } catch { return false; } } else { return false; } } //NCNAME / ID if (typedLiteral.Datatype.Equals(RDFModelEnums.RDFDatatypes.XSD_NCNAME) || typedLiteral.Datatype.Equals(RDFModelEnums.RDFDatatypes.XSD_ID)) { try { XmlConvert.VerifyNCName(typedLiteral.Value); return true; } catch { return false; } } //TOKEN if (typedLiteral.Datatype.Equals(RDFModelEnums.RDFDatatypes.XSD_TOKEN)) { try { XmlConvert.VerifyTOKEN(typedLiteral.Value); return true; } catch { return false; } } //NMTOKEN if (typedLiteral.Datatype.Equals(RDFModelEnums.RDFDatatypes.XSD_NMTOKEN)) { try { XmlConvert.VerifyNMTOKEN(typedLiteral.Value); return true; } catch { return false; } } //NORMALIZED_STRING if (typedLiteral.Datatype.Equals(RDFModelEnums.RDFDatatypes.XSD_NORMALIZEDSTRING)) { if (typedLiteral.Value.IndexOfAny(new Char[] { '\n', '\r', '\t' }) == -1) { return true; } else { return false; } } //LANGUAGE if (typedLiteral.Datatype.Equals(RDFModelEnums.RDFDatatypes.XSD_LANGUAGE)) { if (Regex.IsMatch(typedLiteral.Value, "^[a-zA-Z]{1,8}(-[a-zA-Z0-9]{1,8})*$")) { return true; } else { return false; } } //BASE64_BINARY if (typedLiteral.Datatype.Equals(RDFModelEnums.RDFDatatypes.XSD_BASE64BINARY)) { try { Convert.FromBase64String(typedLiteral.Value); return true; } catch { return false; } } //HEX_BINARY if (typedLiteral.Datatype.Equals(RDFModelEnums.RDFDatatypes.XSD_HEXBINARY)) { if (Regex.IsMatch(typedLiteral.Value, @"^([0-9a-fA-F]{2})*$")) { return true; } else { return false; } } #endregion #region BOOLEAN CATEGORY if (typedLiteral.Datatype.Equals(RDFModelEnums.RDFDatatypes.XSD_BOOLEAN)) { Boolean outBool; if (Boolean.TryParse(typedLiteral.Value, out outBool)) { typedLiteral.Value = (outBool ? "true" : "false"); } else { //Even if lexical space of XSD:BOOLEAN allows 1/0, //it must be converted to true/false value space if (typedLiteral.Value.Equals("1")) { typedLiteral.Value = "true"; } else if(typedLiteral.Value.Equals("0")) { typedLiteral.Value = "false"; } else { return false; } } return true; } #endregion #region DATETIME CATEGORY //DATETIME if (typedLiteral.Datatype.Equals(RDFModelEnums.RDFDatatypes.XSD_DATETIME)) { DateTime parsedDateTime; if (DateTime.TryParseExact(typedLiteral.Value, "yyyy-MM-ddTHH:mm:ss.FFFFFFFK", CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal, out parsedDateTime)) { typedLiteral.Value = parsedDateTime.ToString("yyyy-MM-ddTHH:mm:ss.FFFFFFF", CultureInfo.InvariantCulture); return true; } else if (DateTime.TryParseExact(typedLiteral.Value, "yyyy-MM-ddTHH:mm:ss.FFFFFFF", CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal, out parsedDateTime)) { typedLiteral.Value = parsedDateTime.ToString("yyyy-MM-ddTHH:mm:ss.FFFFFFF", CultureInfo.InvariantCulture); return true; } else if (DateTime.TryParseExact(typedLiteral.Value, "yyyy-MM-ddTHH:mm:ssK", CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal, out parsedDateTime)) { typedLiteral.Value = parsedDateTime.ToString("yyyy-MM-ddTHH:mm:ss", CultureInfo.InvariantCulture); return true; } else if (DateTime.TryParseExact(typedLiteral.Value, "yyyy-MM-ddTHH:mm:ss", CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal, out parsedDateTime)) { typedLiteral.Value = parsedDateTime.ToString("yyyy-MM-ddTHH:mm:ss", CultureInfo.InvariantCulture); return true; } else { return false; } } //DATE if (typedLiteral.Datatype.Equals(RDFModelEnums.RDFDatatypes.XSD_DATE)) { DateTime parsedDateTime; if (DateTime.TryParseExact(typedLiteral.Value, "yyyy-MM-ddK", CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal, out parsedDateTime)) { typedLiteral.Value = parsedDateTime.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture); return true; } else if (DateTime.TryParseExact(typedLiteral.Value, "yyyy-MM-dd", CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal, out parsedDateTime)) { typedLiteral.Value = parsedDateTime.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture); return true; } else { return false; } } //TIME if (typedLiteral.Datatype.Equals(RDFModelEnums.RDFDatatypes.XSD_TIME)) { DateTime parsedDateTime; if (DateTime.TryParseExact(typedLiteral.Value, "HH:mm:ss.FFFFFFFK", CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal, out parsedDateTime)) { typedLiteral.Value = parsedDateTime.ToString("HH:mm:ss.FFFFFFF", CultureInfo.InvariantCulture); return true; } else if (DateTime.TryParseExact(typedLiteral.Value, "HH:mm:ss.FFFFFFF", CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal, out parsedDateTime)) { typedLiteral.Value = parsedDateTime.ToString("HH:mm:ss.FFFFFFF", CultureInfo.InvariantCulture); return true; } else if (DateTime.TryParseExact(typedLiteral.Value, "HH:mm:ssK", CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal, out parsedDateTime)) { typedLiteral.Value = parsedDateTime.ToString("HH:mm:ss", CultureInfo.InvariantCulture); return true; } else if (DateTime.TryParseExact(typedLiteral.Value, "HH:mm:ss", CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal, out parsedDateTime)) { typedLiteral.Value = parsedDateTime.ToString("HH:mm:ss", CultureInfo.InvariantCulture); return true; } else { return false; } } //G_MONTH_DAY if (typedLiteral.Datatype.Equals(RDFModelEnums.RDFDatatypes.XSD_GMONTHDAY)) { DateTime parsedDateTime; if (DateTime.TryParseExact(typedLiteral.Value, "--MM-ddK", CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal, out parsedDateTime)) { typedLiteral.Value = parsedDateTime.ToString("--MM-dd", CultureInfo.InvariantCulture); return true; } else if (DateTime.TryParseExact(typedLiteral.Value, "--MM-dd", CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal, out parsedDateTime)) { typedLiteral.Value = parsedDateTime.ToString("--MM-dd", CultureInfo.InvariantCulture); return true; } else { return false; } } //G_YEAR_MONTH if (typedLiteral.Datatype.Equals(RDFModelEnums.RDFDatatypes.XSD_GYEARMONTH)) { DateTime parsedDateTime; if (DateTime.TryParseExact(typedLiteral.Value, "yyyy-MMK", CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal, out parsedDateTime)) { typedLiteral.Value = parsedDateTime.ToString("yyyy-MM", CultureInfo.InvariantCulture); return true; } else if (DateTime.TryParseExact(typedLiteral.Value, "yyyy-MM", CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal, out parsedDateTime)) { typedLiteral.Value = parsedDateTime.ToString("yyyy-MM", CultureInfo.InvariantCulture); return true; } else { return false; } } //G_YEAR if (typedLiteral.Datatype.Equals(RDFModelEnums.RDFDatatypes.XSD_GYEAR)) { DateTime parsedDateTime; if (DateTime.TryParseExact(typedLiteral.Value, "yyyyK", CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal, out parsedDateTime)) { typedLiteral.Value = parsedDateTime.ToString("yyyy", CultureInfo.InvariantCulture); return true; } else if (DateTime.TryParseExact(typedLiteral.Value, "yyyy", CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal, out parsedDateTime)) { typedLiteral.Value = parsedDateTime.ToString("yyyy", CultureInfo.InvariantCulture); return true; } else { return false; } } //G_MONTH if (typedLiteral.Datatype.Equals(RDFModelEnums.RDFDatatypes.XSD_GMONTH)) { DateTime parsedDateTime; if (DateTime.TryParseExact(typedLiteral.Value, "MMK", CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal, out parsedDateTime)) { typedLiteral.Value = parsedDateTime.ToString("MM", CultureInfo.InvariantCulture); return true; } else if (DateTime.TryParseExact(typedLiteral.Value, "MM", CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal, out parsedDateTime)) { typedLiteral.Value = parsedDateTime.ToString("MM", CultureInfo.InvariantCulture); return true; } else { return false; } } //G_DAY if (typedLiteral.Datatype.Equals(RDFModelEnums.RDFDatatypes.XSD_GDAY)) { DateTime parsedDateTime; if (DateTime.TryParseExact(typedLiteral.Value, "ddK", CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal, out parsedDateTime)) { typedLiteral.Value = parsedDateTime.ToString("dd", CultureInfo.InvariantCulture); return true; } else if (DateTime.TryParseExact(typedLiteral.Value, "dd", CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal, out parsedDateTime)) { typedLiteral.Value = parsedDateTime.ToString("dd", CultureInfo.InvariantCulture); return true; } else { return false; } } #endregion #region TIMESPAN CATEGORY //DURATION if (typedLiteral.Datatype.Equals(RDFModelEnums.RDFDatatypes.XSD_DURATION)) { try { XmlConvert.ToTimeSpan(typedLiteral.Value); return true; } catch { return false; } } #endregion #region NUMERIC CATEGORY //DECIMAL if (typedLiteral.Datatype.Equals(RDFModelEnums.RDFDatatypes.XSD_DECIMAL)) { Decimal outDecimal; if (Decimal.TryParse(typedLiteral.Value, NumberStyles.Integer | NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out outDecimal)) { typedLiteral.Value = Convert.ToString(outDecimal, CultureInfo.InvariantCulture); return true; } else { return false; } } //DOUBLE if (typedLiteral.Datatype.Equals(RDFModelEnums.RDFDatatypes.XSD_DOUBLE)) { Double outDouble; if (Double.TryParse(typedLiteral.Value, NumberStyles.Float, CultureInfo.InvariantCulture, out outDouble)) { typedLiteral.Value = Convert.ToString(outDouble, CultureInfo.InvariantCulture); return true; } else { return false; } } //FLOAT if (typedLiteral.Datatype.Equals(RDFModelEnums.RDFDatatypes.XSD_FLOAT)) { Single outFloat; if (Single.TryParse(typedLiteral.Value, NumberStyles.Float, CultureInfo.InvariantCulture, out outFloat)) { typedLiteral.Value = Convert.ToString(outFloat, CultureInfo.InvariantCulture); return true; } else { return false; } } //INTEGER if (typedLiteral.Datatype.Equals(RDFModelEnums.RDFDatatypes.XSD_INTEGER)) { Decimal outInteger; if (Decimal.TryParse(typedLiteral.Value, NumberStyles.Integer, CultureInfo.InvariantCulture, out outInteger)) { typedLiteral.Value = Convert.ToString(outInteger, CultureInfo.InvariantCulture); return true; } else { return false; } } //LONG if (typedLiteral.Datatype.Equals(RDFModelEnums.RDFDatatypes.XSD_LONG)) { Int64 outLong; if (Int64.TryParse(typedLiteral.Value, NumberStyles.Integer, CultureInfo.InvariantCulture, out outLong)) { typedLiteral.Value = Convert.ToString(outLong, CultureInfo.InvariantCulture); return true; } else { return false; } } //INT if (typedLiteral.Datatype.Equals(RDFModelEnums.RDFDatatypes.XSD_INT)) { Int32 outInt; if (Int32.TryParse(typedLiteral.Value, NumberStyles.Integer, CultureInfo.InvariantCulture, out outInt)) { typedLiteral.Value = Convert.ToString(outInt, CultureInfo.InvariantCulture); return true; } else { return false; } } //SHORT if (typedLiteral.Datatype.Equals(RDFModelEnums.RDFDatatypes.XSD_SHORT)) { Int16 outShort; if (Int16.TryParse(typedLiteral.Value, NumberStyles.Integer, CultureInfo.InvariantCulture, out outShort)) { typedLiteral.Value = Convert.ToString(outShort, CultureInfo.InvariantCulture); return true; } else { return false; } } //BYTE if (typedLiteral.Datatype.Equals(RDFModelEnums.RDFDatatypes.XSD_BYTE)) { SByte outSByte; if (SByte.TryParse(typedLiteral.Value, NumberStyles.Integer, CultureInfo.InvariantCulture, out outSByte)) { typedLiteral.Value = Convert.ToString(outSByte, CultureInfo.InvariantCulture); return true; } else { return false; } } //UNSIGNED LONG if (typedLiteral.Datatype.Equals(RDFModelEnums.RDFDatatypes.XSD_UNSIGNEDLONG)) { UInt64 outULong; if (UInt64.TryParse(typedLiteral.Value, NumberStyles.Integer, CultureInfo.InvariantCulture, out outULong)) { typedLiteral.Value = Convert.ToString(outULong, CultureInfo.InvariantCulture); return true; } else { return false; } } //UNSIGNED INT if (typedLiteral.Datatype.Equals(RDFModelEnums.RDFDatatypes.XSD_UNSIGNEDINT)) { UInt32 outUInt; if (UInt32.TryParse(typedLiteral.Value, NumberStyles.Integer, CultureInfo.InvariantCulture, out outUInt)) { typedLiteral.Value = Convert.ToString(outUInt, CultureInfo.InvariantCulture); return true; } else { return false; } } //UNSIGNED SHORT if (typedLiteral.Datatype.Equals(RDFModelEnums.RDFDatatypes.XSD_UNSIGNEDSHORT)) { UInt16 outUShort; if (UInt16.TryParse(typedLiteral.Value, NumberStyles.Integer, CultureInfo.InvariantCulture, out outUShort)) { typedLiteral.Value = Convert.ToString(outUShort, CultureInfo.InvariantCulture); return true; } else { return false; } } //UNSIGNED BYTE if (typedLiteral.Datatype.Equals(RDFModelEnums.RDFDatatypes.XSD_UNSIGNEDBYTE)) { Byte outByte; if (Byte.TryParse(typedLiteral.Value, NumberStyles.Integer, CultureInfo.InvariantCulture, out outByte)) { typedLiteral.Value = Convert.ToString(outByte, CultureInfo.InvariantCulture); return true; } else { return false; } } //NON-POSITIVE INTEGER [Decimal.MinValue, 0] if (typedLiteral.Datatype.Equals(RDFModelEnums.RDFDatatypes.XSD_NONPOSITIVEINTEGER)) { Decimal outNPInteger; if (Decimal.TryParse(typedLiteral.Value, NumberStyles.Integer, CultureInfo.InvariantCulture, out outNPInteger)) { typedLiteral.Value = Convert.ToString(outNPInteger, CultureInfo.InvariantCulture); if (outNPInteger > 0) { return false; } } else { return false; } return true; } //NEGATIVE INTEGER [Decimal.MinValue, -1] if (typedLiteral.Datatype.Equals(RDFModelEnums.RDFDatatypes.XSD_NEGATIVEINTEGER)) { Decimal outNInteger; if (Decimal.TryParse(typedLiteral.Value, NumberStyles.Integer, CultureInfo.InvariantCulture, out outNInteger)) { typedLiteral.Value = Convert.ToString(outNInteger, CultureInfo.InvariantCulture); if (outNInteger > -1) { return false; } } else { return false; } return true; } //NON-NEGATIVE INTEGER [0, Decimal.MaxValue] if (typedLiteral.Datatype.Equals(RDFModelEnums.RDFDatatypes.XSD_NONNEGATIVEINTEGER)) { Decimal outNNInteger; if (Decimal.TryParse(typedLiteral.Value, NumberStyles.Integer, CultureInfo.InvariantCulture, out outNNInteger)) { typedLiteral.Value = Convert.ToString(outNNInteger, CultureInfo.InvariantCulture); if (outNNInteger < 0) { return false; } } else { return false; } return true; } //POSITIVE INTEGER [1, Decimal.MaxValue] if (typedLiteral.Datatype.Equals(RDFModelEnums.RDFDatatypes.XSD_POSITIVEINTEGER)) { Decimal outPInteger; if (Decimal.TryParse(typedLiteral.Value, NumberStyles.Integer, CultureInfo.InvariantCulture, out outPInteger)) { typedLiteral.Value = Convert.ToString(outPInteger, CultureInfo.InvariantCulture); if (outPInteger < 1) { return false; } } else { return false; } return true; } #endregion } throw new RDFModelException("Cannot validate RDFTypedLiteral because given \"typedLiteral\" parameter is null."); }
/// <summary> /// Given an element representing a RDF container, iterates on its constituent elements /// to build its standard reification triples. /// </summary> internal static void ParseContainerElements(RDFModelEnums.RDFContainerTypes contType, XmlNode container, RDFResource subj, RDFResource pred, RDFGraph result) { //Attach the container as the blank object of the current pred RDFResource obj = new RDFResource(); result.AddTriple(new RDFTriple(subj, pred, obj)); //obj -> rdf:type -> rdf:[Bag|Seq|Alt] switch (contType) { case RDFModelEnums.RDFContainerTypes.Bag: result.AddTriple(new RDFTriple(obj, RDFVocabulary.RDF.TYPE, RDFVocabulary.RDF.BAG)); break; case RDFModelEnums.RDFContainerTypes.Seq: result.AddTriple(new RDFTriple(obj, RDFVocabulary.RDF.TYPE, RDFVocabulary.RDF.SEQ)); break; default: result.AddTriple(new RDFTriple(obj, RDFVocabulary.RDF.TYPE, RDFVocabulary.RDF.ALT)); break; } //Iterate on the container items if (container.HasChildNodes) { IEnumerator elems = container.ChildNodes.GetEnumerator(); List<String> elemVals = new List<String>(); while (elems != null && elems.MoveNext()) { XmlNode elem = (XmlNode)elems.Current; XmlAttribute elemUri = GetRdfResourceAttribute(elem); #region Container Resource Item //This is a container of resources if (elemUri != null) { //Sanitize eventual blank node value detected by presence of "nodeID" attribute if (elemUri.LocalName.Equals("nodeID", StringComparison.Ordinal)) { if (!elemUri.Value.StartsWith("bnode:")) { elemUri.Value = "bnode:" + elemUri.Value; } } //obj -> rdf:_N -> VALUE if (contType == RDFModelEnums.RDFContainerTypes.Alt) { if (!elemVals.Contains(elemUri.Value)) { elemVals.Add(elemUri.Value); result.AddTriple(new RDFTriple(obj, new RDFResource(RDFVocabulary.RDF.BASE_URI + elem.LocalName), new RDFResource(elemUri.Value))); } } else { result.AddTriple(new RDFTriple(obj, new RDFResource(RDFVocabulary.RDF.BASE_URI + elem.LocalName), new RDFResource(elemUri.Value))); } } #endregion #region Container Literal Item //This is a container of literals else { //Parse the literal contained in the item RDFLiteral literal = null; XmlAttribute attr = GetRdfDatatypeAttribute(elem); if (attr != null) { literal = new RDFTypedLiteral(elem.InnerText, RDFModelUtilities.GetDatatypeFromString(attr.InnerText)); } else { attr = GetXmlLangAttribute(elem); literal = new RDFPlainLiteral(elem.InnerText, (attr != null ? attr.InnerText : String.Empty)); } //obj -> rdf:_N -> VALUE if (contType == RDFModelEnums.RDFContainerTypes.Alt) { if (!elemVals.Contains(literal.ToString())) { elemVals.Add(literal.ToString()); result.AddTriple(new RDFTriple(obj, new RDFResource(RDFVocabulary.RDF.BASE_URI + elem.LocalName), literal)); } } else { result.AddTriple(new RDFTriple(obj, new RDFResource(RDFVocabulary.RDF.BASE_URI + elem.LocalName), literal)); } } #endregion } } }
/// <summary> /// Serializes the given graph to the given stream using XML data format. /// </summary> internal static void Serialize(RDFGraph graph, Stream outputStream) { try { #region serialize using (XmlTextWriter rdfxmlWriter = new XmlTextWriter(outputStream, Encoding.UTF8)) { XmlDocument rdfDoc = new XmlDocument(); rdfxmlWriter.Formatting = Formatting.Indented; #region xmlDecl XmlDeclaration xmlDecl = rdfDoc.CreateXmlDeclaration("1.0", "UTF-8", null); rdfDoc.AppendChild(xmlDecl); #endregion #region rdfRoot XmlNode rdfRoot = rdfDoc.CreateNode(XmlNodeType.Element, RDFVocabulary.RDF.PREFIX + ":RDF", RDFVocabulary.RDF.BASE_URI); XmlAttribute rdfRootNS = rdfDoc.CreateAttribute("xmlns:" + RDFVocabulary.RDF.PREFIX); XmlText rdfRootNSText = rdfDoc.CreateTextNode(RDFVocabulary.RDF.BASE_URI); rdfRootNS.AppendChild(rdfRootNSText); rdfRoot.Attributes.Append(rdfRootNS); #region prefixes //Write the graph's prefixes (except for "rdf", which has already been written) graph.GraphMetadata.Namespaces.ForEach(p => { if (!p.Prefix.Equals(RDFVocabulary.RDF.PREFIX, StringComparison.Ordinal) && !p.Prefix.Equals("base", StringComparison.Ordinal)) { XmlAttribute pfRootNS = rdfDoc.CreateAttribute("xmlns:" + p.Prefix); XmlText pfRootNSText = rdfDoc.CreateTextNode(p.ToString()); pfRootNS.AppendChild(pfRootNSText); rdfRoot.Attributes.Append(pfRootNS); } }); //Write the graph's base uri to resolve eventual relative #IDs XmlAttribute pfBaseNS = rdfDoc.CreateAttribute(RDFVocabulary.XML.PREFIX + ":base"); XmlText pfBaseNSText = rdfDoc.CreateTextNode(graph.Context.ToString()); pfBaseNS.AppendChild(pfBaseNSText); rdfRoot.Attributes.Append(pfBaseNS); #endregion #region linq //Group the graph's triples by subj var groupedList = (from triple in graph orderby triple.Subject.ToString() group triple by new { subj = triple.Subject.ToString() }); #endregion #region graph //Iterate over the calculated groups Dictionary <RDFResource, XmlNode> containers = new Dictionary <RDFResource, XmlNode>(); //Floating containers have reification subject which is never object of any graph's triple Boolean floatingContainers = graph.GraphMetadata.Containers.Keys.Any(k => graph.Triples.Values.Count(v => v.Object.Equals(k)) == 0); //Floating collections have reification subject which is never object of any graph's triple Boolean floatingCollections = graph.GraphMetadata.Collections.Keys.Any(k => graph.Triples.Values.Count(v => v.Object.Equals(k)) == 0); foreach (var group in groupedList) { #region subj //Check if the current subj is a container or a collection subj: if so it must be //serialized in the canonical RDF/XML way instead of the "rdf:Description" way XmlNode subjNode = null; String subj = group.Key.subj; //It is a container subj, so add it to the containers pool if (graph.GraphMetadata.Containers.Keys.Any(k => k.ToString().Equals(subj, StringComparison.Ordinal)) && !floatingContainers) { switch (graph.GraphMetadata.Containers.Single(c => c.Key.ToString().Equals(subj, StringComparison.Ordinal)).Value) { case RDFModelEnums.RDFContainerType.Bag: subjNode = rdfDoc.CreateNode(XmlNodeType.Element, RDFVocabulary.RDF.PREFIX + ":Bag", RDFVocabulary.RDF.BASE_URI); containers.Add(new RDFResource(subj), subjNode); break; case RDFModelEnums.RDFContainerType.Seq: subjNode = rdfDoc.CreateNode(XmlNodeType.Element, RDFVocabulary.RDF.PREFIX + ":Seq", RDFVocabulary.RDF.BASE_URI); containers.Add(new RDFResource(subj), subjNode); break; case RDFModelEnums.RDFContainerType.Alt: subjNode = rdfDoc.CreateNode(XmlNodeType.Element, RDFVocabulary.RDF.PREFIX + ":Alt", RDFVocabulary.RDF.BASE_URI); containers.Add(new RDFResource(subj), subjNode); break; } } //It is a subj of a collection of resources, so do not append triples having it as a subject //because we will reconstruct the collection and append it as a whole else if (graph.GraphMetadata.Collections.Keys.Any(k => k.ToString().Equals(subj, StringComparison.Ordinal)) && graph.GraphMetadata.Collections.Single(c => c.Key.ToString().Equals(subj, StringComparison.Ordinal)).Value.ItemType == RDFModelEnums.RDFItemType.Resource && !floatingCollections) { continue; } //It is neither a container or a collection subj else { subjNode = rdfDoc.CreateNode(XmlNodeType.Element, RDFVocabulary.RDF.PREFIX + ":Description", RDFVocabulary.RDF.BASE_URI); //<rdf:Description rdf:nodeID="blankID"> XmlAttribute subjNodeDesc = null; XmlText subjNodeDescText = rdfDoc.CreateTextNode(group.Key.subj); if (group.Key.subj.StartsWith("bnode:")) { subjNodeDescText.InnerText = subjNodeDescText.InnerText.Replace("bnode:", String.Empty); subjNodeDesc = rdfDoc.CreateAttribute(RDFVocabulary.RDF.PREFIX + ":nodeID", RDFVocabulary.RDF.BASE_URI); } //<rdf:Description rdf:about="subjURI"> else { subjNodeDesc = rdfDoc.CreateAttribute(RDFVocabulary.RDF.PREFIX + ":about", RDFVocabulary.RDF.BASE_URI); } subjNodeDesc.AppendChild(subjNodeDescText); subjNode.Attributes.Append(subjNodeDesc); } #endregion #region predObjList //Iterate over the triples of the current group foreach (var triple in group) { //Do not append the triple if it is "SUBJECT rdf:type rdf:[Bag|Seq|Alt]" if (!(triple.Predicate.Equals(RDFVocabulary.RDF.TYPE) && (subjNode.Name.Equals(RDFVocabulary.RDF.PREFIX + ":Bag", StringComparison.Ordinal) || subjNode.Name.Equals(RDFVocabulary.RDF.PREFIX + ":Seq", StringComparison.Ordinal) || subjNode.Name.Equals(RDFVocabulary.RDF.PREFIX + ":Alt", StringComparison.Ordinal)))) { #region pred String predString = triple.Predicate.ToString(); //"<predPREF:predURI" RDFNamespace predNS = (RDFNamespaceRegister.GetByNamespace(predString) ?? RDFModelUtilities.GenerateNamespace(predString, false)); //Refine the pred with eventually necessary sanitizations String predUri = predString.Replace(predNS.ToString(), predNS.Prefix + ":") .Replace(":#", ":") .TrimEnd(new Char[] { ':', '/' }); //Sanitize eventually detected automatic namespace if (predUri.StartsWith("autoNS:")) { predUri = predUri.Replace("autoNS:", string.Empty); } //Do not write "xmlns" attribute if the predUri is the context of the graph XmlNode predNode = null; if (predNS.ToString().Equals(graph.Context.ToString(), StringComparison.Ordinal)) { predNode = rdfDoc.CreateNode(XmlNodeType.Element, predUri, null); } else { predNode = rdfDoc.CreateNode(XmlNodeType.Element, predUri, predNS.ToString()); } #endregion #region object if (triple.TripleFlavor == RDFModelEnums.RDFTripleFlavor.SPO) { //If the object is a container subj, we must append its entire node saved in the containers dictionary if (containers.Keys.Any(k => k.Equals(triple.Object)) && !floatingContainers) { predNode.AppendChild(containers.Single(c => c.Key.Equals(triple.Object)).Value); } //Else, if the object is a subject of a collection of resources, we must append the "rdf:parseType=Collection" attribute to the predicate node else if (graph.GraphMetadata.Collections.Keys.Any(k => k.Equals(triple.Object)) && graph.GraphMetadata.Collections.Single(c => c.Key.Equals(triple.Object)).Value.ItemType == RDFModelEnums.RDFItemType.Resource && !floatingCollections) { XmlAttribute rdfParseType = rdfDoc.CreateAttribute(RDFVocabulary.RDF.PREFIX + ":parseType", RDFVocabulary.RDF.BASE_URI); XmlText rdfParseTypeText = rdfDoc.CreateTextNode("Collection"); rdfParseType.AppendChild(rdfParseTypeText); predNode.Attributes.Append(rdfParseType); //Then we append sequentially the collection elements List <XmlNode> collElements = ReconstructCollection(graph.GraphMetadata, (RDFResource)triple.Object, rdfDoc); collElements.ForEach(c => predNode.AppendChild(c)); } //Else, threat it as a traditional object node else { String objString = triple.Object.ToString(); XmlAttribute predNodeDesc = null; XmlText predNodeDescText = rdfDoc.CreateTextNode(objString); // rdf:nodeID="blankID"> if (objString.StartsWith("bnode:")) { predNodeDescText.InnerText = predNodeDescText.InnerText.Replace("bnode:", String.Empty); predNodeDesc = rdfDoc.CreateAttribute(RDFVocabulary.RDF.PREFIX + ":nodeID", RDFVocabulary.RDF.BASE_URI); } // rdf:resource="objURI"> else { predNodeDesc = rdfDoc.CreateAttribute(RDFVocabulary.RDF.PREFIX + ":resource", RDFVocabulary.RDF.BASE_URI); } predNodeDesc.AppendChild(predNodeDescText); predNode.Attributes.Append(predNodeDesc); } } #endregion #region literal else { #region plain literal if (triple.Object is RDFPlainLiteral) { RDFPlainLiteral pLit = (RDFPlainLiteral)triple.Object; // xml:lang="plitLANG"> if (pLit.Language != String.Empty) { XmlAttribute plainLiteralLangNodeDesc = rdfDoc.CreateAttribute(RDFVocabulary.XML.PREFIX + ":lang", RDFVocabulary.XML.BASE_URI); XmlText plainLiteralLangNodeDescText = rdfDoc.CreateTextNode(pLit.Language); plainLiteralLangNodeDesc.AppendChild(plainLiteralLangNodeDescText); predNode.Attributes.Append(plainLiteralLangNodeDesc); } } #endregion #region typed literal // rdf:datatype="tlitURI"> else { RDFTypedLiteral tLit = (RDFTypedLiteral)triple.Object; XmlAttribute typedLiteralNodeDesc = rdfDoc.CreateAttribute(RDFVocabulary.RDF.PREFIX + ":datatype", RDFVocabulary.RDF.BASE_URI); XmlText typedLiteralNodeDescText = rdfDoc.CreateTextNode(RDFModelUtilities.GetDatatypeFromEnum(tLit.Datatype)); typedLiteralNodeDesc.AppendChild(typedLiteralNodeDescText); predNode.Attributes.Append(typedLiteralNodeDesc); } #endregion //litVALUE</predPREF:predURI>" XmlText litNodeDescText = rdfDoc.CreateTextNode(((RDFLiteral)triple.Object).Value); predNode.AppendChild(litNodeDescText); } #endregion subjNode.AppendChild(predNode); } } //Raw containers must not be written as-is, instead they have to be saved //and attached when their subj is found later as object of a triple if (!subjNode.Name.Equals(RDFVocabulary.RDF.PREFIX + ":Bag", StringComparison.Ordinal) && !subjNode.Name.Equals(RDFVocabulary.RDF.PREFIX + ":Seq", StringComparison.Ordinal) && !subjNode.Name.Equals(RDFVocabulary.RDF.PREFIX + ":Alt", StringComparison.Ordinal)) { rdfRoot.AppendChild(subjNode); } #endregion } #endregion rdfDoc.AppendChild(rdfRoot); #endregion rdfDoc.Save(rdfxmlWriter); } #endregion } catch (Exception ex) { throw new RDFModelException("Cannot serialize Xml because: " + ex.Message, ex); } }
/// <summary> /// Given an element representing a RDF container, iterates on its constituent elements /// to build its standard reification triples. /// </summary> internal static void ParseContainerElements(RDFModelEnums.RDFContainerType contType, XmlNode container, RDFResource subj, RDFResource pred, RDFGraph result) { //Attach the container as the blank object of the current pred RDFResource obj = new RDFResource(); result.AddTriple(new RDFTriple(subj, pred, obj)); //obj -> rdf:type -> rdf:[Bag|Seq|Alt] switch (contType) { case RDFModelEnums.RDFContainerType.Bag: result.AddTriple(new RDFTriple(obj, RDFVocabulary.RDF.TYPE, RDFVocabulary.RDF.BAG)); break; case RDFModelEnums.RDFContainerType.Seq: result.AddTriple(new RDFTriple(obj, RDFVocabulary.RDF.TYPE, RDFVocabulary.RDF.SEQ)); break; default: result.AddTriple(new RDFTriple(obj, RDFVocabulary.RDF.TYPE, RDFVocabulary.RDF.ALT)); break; } //Iterate on the container items if (container.HasChildNodes) { IEnumerator elems = container.ChildNodes.GetEnumerator(); List <String> elemVals = new List <String>(); while (elems != null && elems.MoveNext()) { XmlNode elem = (XmlNode)elems.Current; XmlAttribute elemUri = GetRdfResourceAttribute(elem); #region Container Resource Item //This is a container of resources if (elemUri != null) { //Sanitize eventual blank node value detected by presence of "nodeID" attribute if (elemUri.LocalName.Equals("nodeID", StringComparison.Ordinal)) { if (!elemUri.Value.StartsWith("bnode:")) { elemUri.Value = "bnode:" + elemUri.Value; } } //obj -> rdf:_N -> VALUE if (contType == RDFModelEnums.RDFContainerType.Alt) { if (!elemVals.Contains(elemUri.Value)) { elemVals.Add(elemUri.Value); result.AddTriple(new RDFTriple(obj, new RDFResource(RDFVocabulary.RDF.BASE_URI + elem.LocalName), new RDFResource(elemUri.Value))); } } else { result.AddTriple(new RDFTriple(obj, new RDFResource(RDFVocabulary.RDF.BASE_URI + elem.LocalName), new RDFResource(elemUri.Value))); } } #endregion #region Container Literal Item //This is a container of literals else { //Parse the literal contained in the item RDFLiteral literal = null; XmlAttribute attr = GetRdfDatatypeAttribute(elem); if (attr != null) { literal = new RDFTypedLiteral(elem.InnerText, RDFModelUtilities.GetDatatypeFromString(attr.InnerText)); } else { attr = GetXmlLangAttribute(elem); literal = new RDFPlainLiteral(elem.InnerText, (attr != null ? attr.InnerText : String.Empty)); } //obj -> rdf:_N -> VALUE if (contType == RDFModelEnums.RDFContainerType.Alt) { if (!elemVals.Contains(literal.ToString())) { elemVals.Add(literal.ToString()); result.AddTriple(new RDFTriple(obj, new RDFResource(RDFVocabulary.RDF.BASE_URI + elem.LocalName), literal)); } } else { result.AddTriple(new RDFTriple(obj, new RDFResource(RDFVocabulary.RDF.BASE_URI + elem.LocalName), literal)); } } #endregion } } }
/// <summary> /// Deserializes the given Xml stream to a graph. /// </summary> internal static RDFGraph Deserialize(Stream inputStream) { try { #region deserialize XmlReaderSettings xrs = new XmlReaderSettings(); xrs.IgnoreComments = true; xrs.DtdProcessing = DtdProcessing.Ignore; RDFGraph result = new RDFGraph(); using (XmlReader xr = XmlReader.Create(new StreamReader(inputStream, Encoding.UTF8), xrs)) { #region load XmlDocument xmlDoc = new XmlDocument(); xmlDoc.Load(xr); #endregion #region root //Prepare the namespace table for the Xml selections var nsMgr = new XmlNamespaceManager(new NameTable()); nsMgr.AddNamespace(RDFVocabulary.RDF.PREFIX, RDFVocabulary.RDF.BASE_URI); //Select "rdf:RDF" root node XmlNode rdfRDF = GetRdfRootNode(xmlDoc, nsMgr); #endregion #region prefixes //Select "xmlns" attributes and try to add them to the namespace register var xmlnsAttrs = GetXmlnsNamespaces(rdfRDF, nsMgr); //Try to get the "xml:base" attribute, which is needed to resolve eventual relative #IDs in "rdf:about" nodes //If it is not found, set it to the graph Uri Uri xmlBase = null; if (xmlnsAttrs != null && xmlnsAttrs.Count > 0) { var xmlBaseAttr = (rdfRDF.Attributes["xml:base"] ?? rdfRDF.Attributes["xmlns"]); if (xmlBaseAttr != null) { xmlBase = RDFModelUtilities.GetUriFromString(xmlBaseAttr.Value); } } //Always keep in synch the Context and the xmlBase if (xmlBase != null) { result.SetContext(xmlBase); } else { xmlBase = result.Context; } #endregion #region elements //Parse resource elements, which are the childs of root node and represent the subjects if (rdfRDF.HasChildNodes) { var subjNodesEnum = rdfRDF.ChildNodes.GetEnumerator(); while (subjNodesEnum != null && subjNodesEnum.MoveNext()) { #region subj //Get the current resource node XmlNode subjNode = (XmlNode)subjNodesEnum.Current; RDFResource subj = GetSubjectNode(subjNode, xmlBase, result); if (subj == null) { continue; } #endregion #region predObjList //Parse pred elements, which are the childs of subj element if (subjNode.HasChildNodes) { IEnumerator predNodesEnum = subjNode.ChildNodes.GetEnumerator(); while (predNodesEnum != null && predNodesEnum.MoveNext()) { //Get the current pred node RDFResource pred = null; XmlNode predNode = (XmlNode)predNodesEnum.Current; if (predNode.NamespaceURI == String.Empty) { pred = new RDFResource(xmlBase + predNode.LocalName); } else { pred = (predNode.LocalName.StartsWith("autoNS") ? new RDFResource(predNode.NamespaceURI) : new RDFResource(predNode.NamespaceURI + predNode.LocalName)); } #region object //Check if there is a "rdf:about" or a "rdf:resource" attribute XmlAttribute rdfObject = (GetRdfAboutAttribute(predNode) ?? GetRdfResourceAttribute(predNode)); if (rdfObject != null) { //Attribute found, but we must check if it is "rdf:ID", "rdf:nodeID" or a relative Uri String rdfObjectValue = ResolveRelativeNode(rdfObject, xmlBase); RDFResource obj = new RDFResource(rdfObjectValue); result.AddTriple(new RDFTriple(subj, pred, obj)); continue; } #endregion #region typed literal //Check if there is a "rdf:datatype" attribute XmlAttribute rdfDatatype = GetRdfDatatypeAttribute(predNode); if (rdfDatatype != null) { RDFModelEnums.RDFDatatype dt = RDFModelUtilities.GetDatatypeFromString(rdfDatatype.Value); RDFTypedLiteral tLit = new RDFTypedLiteral(HttpUtility.HtmlDecode(predNode.InnerText), dt); result.AddTriple(new RDFTriple(subj, pred, tLit)); continue; } //Check if there is a "rdf:parseType=Literal" attribute XmlAttribute parseLiteral = GetParseTypeLiteralAttribute(predNode); if (parseLiteral != null) { RDFTypedLiteral tLit = new RDFTypedLiteral(HttpUtility.HtmlDecode(predNode.InnerXml), RDFModelEnums.RDFDatatype.RDFS_LITERAL); result.AddTriple(new RDFTriple(subj, pred, tLit)); continue; } #endregion #region plain literal //Check if there is a "xml:lang" attribute, or if a unique textual child XmlAttribute xmlLang = GetXmlLangAttribute(predNode); if (xmlLang != null || (predNode.HasChildNodes && predNode.ChildNodes.Count == 1 && predNode.ChildNodes[0].NodeType == XmlNodeType.Text)) { RDFPlainLiteral pLit = new RDFPlainLiteral(HttpUtility.HtmlDecode(predNode.InnerText), (xmlLang != null ? xmlLang.Value : String.Empty)); result.AddTriple(new RDFTriple(subj, pred, pLit)); continue; } #endregion #region collection //Check if there is a "rdf:parseType=Collection" attribute XmlAttribute rdfCollect = GetParseTypeCollectionAttribute(predNode); if (rdfCollect != null) { ParseCollectionElements(xmlBase, predNode, subj, pred, result); continue; } #endregion #region container //Check if there is a "rdf:[Bag|Seq|Alt]" child node XmlNode container = GetContainerNode(predNode); if (container != null) { //Distinguish the right type of RDF container to build if (container.LocalName.Equals(RDFVocabulary.RDF.PREFIX + ":Bag", StringComparison.Ordinal) || container.LocalName.Equals("Bag", StringComparison.Ordinal)) { ParseContainerElements(RDFModelEnums.RDFContainerType.Bag, container, subj, pred, result); } else if (container.LocalName.Equals(RDFVocabulary.RDF.PREFIX + ":Seq", StringComparison.Ordinal) || container.LocalName.Equals("Seq", StringComparison.Ordinal)) { ParseContainerElements(RDFModelEnums.RDFContainerType.Seq, container, subj, pred, result); } else if (container.LocalName.Equals(RDFVocabulary.RDF.PREFIX + ":Alt", StringComparison.Ordinal) || container.LocalName.Equals("Alt", StringComparison.Ordinal)) { ParseContainerElements(RDFModelEnums.RDFContainerType.Alt, container, subj, pred, result); } } #endregion } } #endregion } } #endregion } return(result); #endregion } catch (Exception ex) { throw new RDFModelException("Cannot deserialize Xml because: " + ex.Message, ex); } }
/// <summary> /// Deserializes the given Xml filepath to a graph. /// </summary> internal static RDFGraph Deserialize(String filepath) { try { #region deserialize XmlReaderSettings xrs = new XmlReaderSettings(); xrs.IgnoreComments = true; xrs.DtdProcessing = DtdProcessing.Ignore; RDFGraph result = new RDFGraph(); using(XmlReader xr = XmlReader.Create(new StreamReader(filepath, Encoding.UTF8), xrs)) { #region load XmlDocument xmlDoc = new XmlDocument(); xmlDoc.Load(xr); #endregion #region root //Prepare the namespace table for the Xml selections var nsMgr = new XmlNamespaceManager(new NameTable()); nsMgr.AddNamespace(RDFVocabulary.RDF.PREFIX, RDFVocabulary.RDF.BASE_URI); //Select "rdf:RDF" root node XmlNode rdfRDF = RDFModelUtilities.GetRdfRootNode(xmlDoc, nsMgr); #endregion #region prefixes //Select "xmlns" attributes and try to add them to the namespace register var xmlnsAttrs = RDFModelUtilities.GetXmlnsNamespaces(rdfRDF, nsMgr); //Try to get the "xml:base" attribute, which is needed to resolve eventual relative #IDs in "rdf:about" nodes //If it is not found, set it to the graph Uri Uri xmlBase = null; if (xmlnsAttrs != null && xmlnsAttrs.Count > 0) { var xmlBaseAttr = (rdfRDF.Attributes["xml:base"] ?? rdfRDF.Attributes["xmlns"]); if (xmlBaseAttr != null) { xmlBase = RDFModelUtilities.GetUriFromString(xmlBaseAttr.Value); } } //Always keep in synch the Context and the xmlBase if (xmlBase != null) { result.SetContext(xmlBase); } else { xmlBase = result.Context; } #endregion #region elements //Parse resource elements, which are the childs of root node and represent the subjects if (rdfRDF.HasChildNodes) { var subjNodesEnum = rdfRDF.ChildNodes.GetEnumerator(); while (subjNodesEnum != null && subjNodesEnum.MoveNext()) { #region subj //Get the current resource node XmlNode subjNode = (XmlNode)subjNodesEnum.Current; RDFResource subj = RDFModelUtilities.GetSubjectNode(subjNode, xmlBase, result); if (subj == null) { continue; } #endregion #region predObjList //Parse pred elements, which are the childs of subj element if (subjNode.HasChildNodes) { IEnumerator predNodesEnum = subjNode.ChildNodes.GetEnumerator(); while (predNodesEnum != null && predNodesEnum.MoveNext()) { //Get the current pred node RDFResource pred = null; XmlNode predNode = (XmlNode)predNodesEnum.Current; if (predNode.NamespaceURI == String.Empty) { pred = new RDFResource(xmlBase + predNode.LocalName); } else { pred = (predNode.LocalName.StartsWith("autoNS") ? new RDFResource(predNode.NamespaceURI) : new RDFResource(predNode.NamespaceURI + predNode.LocalName)); } #region object //Check if there is a "rdf:about" or a "rdf:resource" attribute XmlAttribute rdfObject = (RDFModelUtilities.GetRdfAboutAttribute(predNode) ?? RDFModelUtilities.GetRdfResourceAttribute(predNode)); if (rdfObject != null) { //Attribute found, but we must check if it is "rdf:ID", "rdf:nodeID" or a relative Uri String rdfObjectValue = RDFModelUtilities.ResolveRelativeNode(rdfObject, xmlBase); RDFResource obj = new RDFResource(rdfObjectValue); result.AddTriple(new RDFTriple(subj, pred, obj)); continue; } #endregion #region typed literal //Check if there is a "rdf:datatype" attribute XmlAttribute rdfDatatype = RDFModelUtilities.GetRdfDatatypeAttribute(predNode); if (rdfDatatype != null) { RDFDatatype dt = RDFModelUtilities.GetDatatypeFromString(rdfDatatype.Value); RDFTypedLiteral tLit = new RDFTypedLiteral(HttpUtility.HtmlDecode(predNode.InnerText), dt); result.AddTriple(new RDFTriple(subj, pred, tLit)); continue; } //Check if there is a "rdf:parseType=Literal" attribute XmlAttribute parseLiteral = RDFModelUtilities.GetParseTypeLiteralAttribute(predNode); if (parseLiteral != null) { RDFTypedLiteral tLit = new RDFTypedLiteral(HttpUtility.HtmlDecode(predNode.InnerXml), RDFDatatypeRegister.GetByPrefixAndDatatype(RDFVocabulary.RDFS.PREFIX, "Literal")); result.AddTriple(new RDFTriple(subj, pred, tLit)); continue; } #endregion #region plain literal //Check if there is a "xml:lang" attribute, or if a unique textual child XmlAttribute xmlLang = RDFModelUtilities.GetXmlLangAttribute(predNode); if (xmlLang != null || (predNode.HasChildNodes && predNode.ChildNodes.Count == 1 && predNode.ChildNodes[0].NodeType == XmlNodeType.Text)) { RDFPlainLiteral pLit = new RDFPlainLiteral(HttpUtility.HtmlDecode(predNode.InnerText), (xmlLang != null ? xmlLang.Value : String.Empty)); result.AddTriple(new RDFTriple(subj, pred, pLit)); continue; } #endregion #region collection //Check if there is a "rdf:parseType=Collection" attribute XmlAttribute rdfCollect = RDFModelUtilities.GetParseTypeCollectionAttribute(predNode); if (rdfCollect != null) { RDFModelUtilities.ParseCollectionElements(xmlBase, predNode, subj, pred, result); continue; } #endregion #region container //Check if there is a "rdf:[Bag|Seq|Alt]" child node XmlNode container = RDFModelUtilities.GetContainerNode(predNode); if (container != null) { //Distinguish the right type of RDF container to build if (container.LocalName.Equals(RDFVocabulary.RDF.PREFIX + ":Bag", StringComparison.Ordinal) || container.LocalName.Equals("Bag", StringComparison.Ordinal)) { RDFModelUtilities.ParseContainerElements(RDFModelEnums.RDFContainerTypes.Bag, container, subj, pred, result); } else if (container.LocalName.Equals(RDFVocabulary.RDF.PREFIX + ":Seq", StringComparison.Ordinal) || container.LocalName.Equals("Seq", StringComparison.Ordinal)) { RDFModelUtilities.ParseContainerElements(RDFModelEnums.RDFContainerTypes.Seq, container, subj, pred, result); } else if (container.LocalName.Equals(RDFVocabulary.RDF.PREFIX + ":Alt", StringComparison.Ordinal) || container.LocalName.Equals("Alt", StringComparison.Ordinal)) { RDFModelUtilities.ParseContainerElements(RDFModelEnums.RDFContainerTypes.Alt, container, subj, pred, result); } } #endregion } } #endregion } } #endregion } return result; #endregion } catch (Exception ex) { throw new RDFModelException("Cannot deserialize Xml because: " + ex.Message, ex); } }
/// <summary> /// Deserializes the given N-Triples stream to a graph. /// </summary> internal static RDFGraph Deserialize(Stream inputStream) { Int64 ntripleIndex = 0; try { #region deserialize using (StreamReader sr = new StreamReader(inputStream, Encoding.ASCII)) { RDFGraph result = new RDFGraph(); String ntriple = String.Empty; String[] tokens = new String[3]; RDFResource S = null; RDFResource P = null; RDFResource O = null; RDFLiteral L = null; while((ntriple = sr.ReadLine()) != null) { ntripleIndex++; #region sanitize & tokenize //Cleanup previous data S = null; tokens[0] = String.Empty; P = null; tokens[1] = String.Empty; O = null; L = null; tokens[2] = String.Empty; //Preliminary sanitizations: clean trailing space-like chars ntriple = ntriple.Trim(new Char[] { ' ', '\t', '\r', '\n' }); //Skip empty or comment lines if (ntriple == String.Empty || ntriple.StartsWith("#")) { continue; } //Tokenizes the sanitized triple tokens = TokenizeNTriple(ntriple); #endregion #region subj String subj = tokens[0].TrimStart(new Char[] { '<' }) .TrimEnd(new Char[] { '>' }) .Replace("_:", "bnode:"); S = new RDFResource(RDFModelUtilities.ASCII_To_Unicode(subj)); #endregion #region pred String pred = tokens[1].TrimStart(new Char[] { '<' }) .TrimEnd(new Char[] { '>' }); P = new RDFResource(RDFModelUtilities.ASCII_To_Unicode(pred)); #endregion #region object if (tokens[2].StartsWith("<") || tokens[2].StartsWith("bnode:") || tokens[2].StartsWith("_:")) { String obj = tokens[2].TrimStart(new Char[] { '<' }) .TrimEnd(new Char[] { '>' }) .Replace("_:", "bnode:") .Trim(new Char[] { ' ', '\n', '\t', '\r' }); O = new RDFResource(RDFModelUtilities.ASCII_To_Unicode(obj)); } #endregion #region literal else { #region sanitize tokens[2] = regexSqt.Replace(tokens[2], String.Empty); tokens[2] = regexEqt.Replace(tokens[2], String.Empty); tokens[2] = tokens[2].Replace("\\\\", "\\") .Replace("\\\"", "\"") .Replace("\\n", "\n") .Replace("\\t", "\t") .Replace("\\r", "\r"); tokens[2] = RDFModelUtilities.ASCII_To_Unicode(tokens[2]); #endregion #region plain literal if (!tokens[2].Contains("^^") || tokens[2].EndsWith("^^") || tokens[2].Substring(tokens[2].LastIndexOf("^^", StringComparison.Ordinal) + 2, 1) != "<") { if (regexLPL.Match(tokens[2]).Success) { tokens[2] = tokens[2].Replace("\"@", "@"); String pLitValue = tokens[2].Substring(0, tokens[2].LastIndexOf("@", StringComparison.Ordinal)); String pLitLang = tokens[2].Substring(tokens[2].LastIndexOf("@", StringComparison.Ordinal) + 1); L = new RDFPlainLiteral(HttpUtility.HtmlDecode(pLitValue), pLitLang); } else { L = new RDFPlainLiteral(HttpUtility.HtmlDecode(tokens[2])); } } #endregion #region typed literal else { tokens[2] = tokens[2].Replace("\"^^", "^^"); String tLitValue = tokens[2].Substring(0, tokens[2].LastIndexOf("^^", StringComparison.Ordinal)); String tLitDatatype = tokens[2].Substring(tokens[2].LastIndexOf("^^", StringComparison.Ordinal) + 2) .TrimStart(new Char[] { '<' }) .TrimEnd(new Char[] { '>' }); RDFModelEnums.RDFDatatypes dt = RDFModelUtilities.GetDatatypeFromString(tLitDatatype); L = new RDFTypedLiteral(HttpUtility.HtmlDecode(tLitValue), dt); } #endregion } #endregion #region addtriple if (O != null) { result.AddTriple(new RDFTriple(S, P, O)); } else { result.AddTriple(new RDFTriple(S, P, L)); } #endregion } return result; } #endregion } catch(Exception ex) { throw new RDFModelException("Cannot deserialize N-Triples (line " + ntripleIndex + ") because: " + ex.Message, ex); } }
/// <summary> /// Deserializes the given N-Quads stream to a memory store. /// </summary> internal static RDFMemoryStore Deserialize(Stream inputStream) { Int64 nquadIndex = 0; try { #region deserialize using (StreamReader sr = new StreamReader(inputStream, Encoding.ASCII)) { RDFMemoryStore result = new RDFMemoryStore(); String nquad = String.Empty; String[] tokens = new String[4]; RDFResource S = null; RDFResource P = null; RDFResource O = null; RDFLiteral L = null; RDFContext C = new RDFContext(); while((nquad = sr.ReadLine()) != null) { nquadIndex++; #region sanitize & tokenize //Cleanup previous data S = null; tokens[0] = String.Empty; P = null; tokens[1] = String.Empty; O = null; L = null; tokens[2] = String.Empty; C = new RDFContext(); tokens[3] = String.Empty; //Preliminary sanitizations: clean trailing space-like chars nquad = nquad.Trim(new Char[] { ' ', '\t', '\r', '\n' }); //Skip empty or comment lines if (nquad == String.Empty || nquad.StartsWith("#")) { continue; } //Tokenizes the sanitized quad tokens = TokenizeNQuad(nquad); #endregion #region subj String subj = tokens[0].TrimStart(new Char[] { '<' }) .TrimEnd(new Char[] { '>' }) .Replace("_:", "bnode:"); S = new RDFResource(RDFModelUtilities.ASCII_To_Unicode(subj)); #endregion #region pred String pred = tokens[1].TrimStart(new Char[] { '<' }) .TrimEnd(new Char[] { '>' }); P = new RDFResource(RDFModelUtilities.ASCII_To_Unicode(pred)); #endregion #region object if (tokens[2].StartsWith("<") || tokens[2].StartsWith("bnode:") || tokens[2].StartsWith("_:")) { String obj = tokens[2].TrimStart(new Char[] { '<' }) .TrimEnd(new Char[] { '>' }) .Replace("_:", "bnode:") .Trim(new Char[] { ' ', '\n', '\t', '\r' }); O = new RDFResource(RDFModelUtilities.ASCII_To_Unicode(obj)); } #endregion #region literal else { #region sanitize tokens[2] = RDFNTriples.regexSqt.Replace(tokens[2], String.Empty); tokens[2] = RDFNTriples.regexEqt.Replace(tokens[2], String.Empty); tokens[2] = tokens[2].Replace("\\\\", "\\") .Replace("\\\"", "\"") .Replace("\\n", "\n") .Replace("\\t", "\t") .Replace("\\r", "\r"); tokens[2] = RDFModelUtilities.ASCII_To_Unicode(tokens[2]); #endregion #region plain literal if (!tokens[2].Contains("^^") || tokens[2].EndsWith("^^") || tokens[2].Substring(tokens[2].LastIndexOf("^^", StringComparison.Ordinal) + 2, 1) != "<") { if (RDFNTriples.regexLPL.Match(tokens[2]).Success) { tokens[2] = tokens[2].Replace("\"@", "@"); String pLitValue = tokens[2].Substring(0, tokens[2].LastIndexOf("@", StringComparison.Ordinal)); String pLitLang = tokens[2].Substring(tokens[2].LastIndexOf("@", StringComparison.Ordinal) + 1); L = new RDFPlainLiteral(HttpUtility.HtmlDecode(pLitValue), pLitLang); } else { L = new RDFPlainLiteral(HttpUtility.HtmlDecode(tokens[2])); } } #endregion #region typed literal else { tokens[2] = tokens[2].Replace("\"^^", "^^"); String tLitValue = tokens[2].Substring(0, tokens[2].LastIndexOf("^^", StringComparison.Ordinal)); String tLitDatatype = tokens[2].Substring(tokens[2].LastIndexOf("^^", StringComparison.Ordinal) + 2) .TrimStart(new Char[] { '<' }) .TrimEnd(new Char[] { '>' }); RDFModelEnums.RDFDatatypes dt = RDFModelUtilities.GetDatatypeFromString(tLitDatatype); L = new RDFTypedLiteral(HttpUtility.HtmlDecode(tLitValue), dt); } #endregion } #endregion #region context if (!String.IsNullOrEmpty(tokens[3])) { String ctx = tokens[3].TrimStart(new Char[] { '<' }) .TrimEnd(new Char[] { '>' }); Uri ctxUri = null; if (Uri.TryCreate(ctx, UriKind.Absolute, out ctxUri)) { C = new RDFContext(RDFModelUtilities.ASCII_To_Unicode(ctxUri.ToString())); } else { throw new RDFModelException("found context '" + ctx +"' which is not a well-formed absolute Uri"); } } #endregion #region addquadruple if (O != null) { result.AddQuadruple(new RDFQuadruple(C, S, P, O)); } else { result.AddQuadruple(new RDFQuadruple(C, S, P, L)); } #endregion } return result; } #endregion } catch(Exception ex) { throw new RDFModelException("Cannot deserialize N-Quads (line " + nquadIndex + ") because: " + ex.Message, ex); } }
/// <summary> /// Serializes the given graph to the given stream using XML data format. /// </summary> internal static void Serialize(RDFGraph graph, Stream outputStream) { try { #region serialize using (XmlTextWriter rdfxmlWriter = new XmlTextWriter(outputStream, Encoding.UTF8)) { XmlDocument rdfDoc = new XmlDocument(); rdfxmlWriter.Formatting = Formatting.Indented; #region xmlDecl XmlDeclaration xmlDecl = rdfDoc.CreateXmlDeclaration("1.0", "UTF-8", null); rdfDoc.AppendChild(xmlDecl); #endregion #region rdfRoot XmlNode rdfRoot = rdfDoc.CreateNode(XmlNodeType.Element, RDFVocabulary.RDF.PREFIX + ":RDF", RDFVocabulary.RDF.BASE_URI); XmlAttribute rdfRootNS = rdfDoc.CreateAttribute("xmlns:" + RDFVocabulary.RDF.PREFIX); XmlText rdfRootNSText = rdfDoc.CreateTextNode(RDFVocabulary.RDF.BASE_URI); rdfRootNS.AppendChild(rdfRootNSText); rdfRoot.Attributes.Append(rdfRootNS); #region prefixes //Write the prefixes (except for "rdf" and "base") var graphNamespaces = RDFModelUtilities.GetGraphNamespaces(graph); var autoNamespaces = GetAutomaticNamespaces(graph); graphNamespaces.Union(autoNamespaces).ToList().ForEach(p => { if(!p.NamespacePrefix.Equals(RDFVocabulary.RDF.PREFIX, StringComparison.Ordinal) && !p.NamespacePrefix.Equals("base", StringComparison.Ordinal)) { XmlAttribute pfRootNS = rdfDoc.CreateAttribute("xmlns:" + p.NamespacePrefix); XmlText pfRootNSText = rdfDoc.CreateTextNode(p.ToString()); pfRootNS.AppendChild(pfRootNSText); rdfRoot.Attributes.Append(pfRootNS); } }); //Write the graph's base uri to resolve eventual relative #IDs XmlAttribute pfBaseNS = rdfDoc.CreateAttribute(RDFVocabulary.XML.PREFIX + ":base"); XmlText pfBaseNSText = rdfDoc.CreateTextNode(graph.Context.ToString()); pfBaseNS.AppendChild(pfBaseNSText); rdfRoot.Attributes.Append(pfBaseNS); #endregion #region linq //Group the graph's triples by subj var groupedList = (from triple in graph orderby triple.Subject.ToString() group triple by new { subj = triple.Subject.ToString() }); #endregion #region graph //Iterate over the calculated groups Dictionary<RDFResource, XmlNode> containers = new Dictionary<RDFResource, XmlNode>(); //Floating containers have reification subject which is never object of any graph's triple Boolean floatingContainers = graph.GraphMetadata.Containers.Keys.Any(k => graph.Triples.Values.Count(v => v.Object.Equals(k)) == 0); //Floating collections have reification subject which is never object of any graph's triple Boolean floatingCollections = graph.GraphMetadata.Collections.Keys.Any(k => graph.Triples.Values.Count(v => v.Object.Equals(k)) == 0); foreach (var group in groupedList) { #region subj //Check if the current subj is a container or a collection subj: if so it must be //serialized in the canonical RDF/XML way instead of the "rdf:Description" way XmlNode subjNode = null; String subj = group.Key.subj; //It is a container subj, so add it to the containers pool if (graph.GraphMetadata.Containers.Keys.Any(k => k.ToString().Equals(subj, StringComparison.Ordinal)) && !floatingContainers) { switch (graph.GraphMetadata.Containers.Single(c => c.Key.ToString().Equals(subj, StringComparison.Ordinal)).Value) { case RDFModelEnums.RDFContainerTypes.Bag: subjNode = rdfDoc.CreateNode(XmlNodeType.Element, RDFVocabulary.RDF.PREFIX + ":Bag", RDFVocabulary.RDF.BASE_URI); containers.Add(new RDFResource(subj), subjNode); break; case RDFModelEnums.RDFContainerTypes.Seq: subjNode = rdfDoc.CreateNode(XmlNodeType.Element, RDFVocabulary.RDF.PREFIX + ":Seq", RDFVocabulary.RDF.BASE_URI); containers.Add(new RDFResource(subj), subjNode); break; case RDFModelEnums.RDFContainerTypes.Alt: subjNode = rdfDoc.CreateNode(XmlNodeType.Element, RDFVocabulary.RDF.PREFIX + ":Alt", RDFVocabulary.RDF.BASE_URI); containers.Add(new RDFResource(subj), subjNode); break; } } //It is a subj of a collection of resources, so do not append triples having it as a subject //because we will reconstruct the collection and append it as a whole else if (graph.GraphMetadata.Collections.Keys.Any(k => k.ToString().Equals(subj, StringComparison.Ordinal)) && graph.GraphMetadata.Collections.Single(c => c.Key.ToString().Equals(subj, StringComparison.Ordinal)).Value.ItemType == RDFModelEnums.RDFItemTypes.Resource && !floatingCollections) { continue; } //It is neither a container or a collection subj else { subjNode = rdfDoc.CreateNode(XmlNodeType.Element, RDFVocabulary.RDF.PREFIX + ":Description", RDFVocabulary.RDF.BASE_URI); //<rdf:Description rdf:nodeID="blankID"> XmlAttribute subjNodeDesc = null; XmlText subjNodeDescText = rdfDoc.CreateTextNode(group.Key.subj); if (group.Key.subj.StartsWith("bnode:")) { subjNodeDesc = rdfDoc.CreateAttribute(RDFVocabulary.RDF.PREFIX + ":nodeID", RDFVocabulary.RDF.BASE_URI); } //<rdf:Description rdf:about="subjURI"> else { subjNodeDesc = rdfDoc.CreateAttribute(RDFVocabulary.RDF.PREFIX + ":about", RDFVocabulary.RDF.BASE_URI); } subjNodeDesc.AppendChild(subjNodeDescText); subjNode.Attributes.Append(subjNodeDesc); } #endregion #region predObjList //Iterate over the triples of the current group foreach (var triple in group) { //Do not append the triple if it is "SUBJECT rdf:type rdf:[Bag|Seq|Alt]" if (!(triple.Predicate.Equals(RDFVocabulary.RDF.TYPE) && (subjNode.Name.Equals(RDFVocabulary.RDF.PREFIX + ":Bag", StringComparison.Ordinal) || subjNode.Name.Equals(RDFVocabulary.RDF.PREFIX + ":Seq", StringComparison.Ordinal) || subjNode.Name.Equals(RDFVocabulary.RDF.PREFIX + ":Alt", StringComparison.Ordinal)))) { #region pred String predString = triple.Predicate.ToString(); //"<predPREF:predURI" RDFNamespace predNS = RDFNamespaceRegister.GetByUri(predString) ?? GenerateNamespace(predString, false); String predUri = (predNS.NamespacePrefix.Equals("autoNS", StringComparison.OrdinalIgnoreCase) ? predString.Replace(predNS.ToString(), autoNamespaces.Find(ns => ns.NamespaceUri.Equals(predNS.NamespaceUri)).NamespacePrefix + ":") : predString.Replace(predNS.ToString(), predNS.NamespacePrefix + ":")) .Replace(":#", ":") .TrimEnd(new Char[] { ':', '/' }); try { var predUriQName = new RDFTypedLiteral(predUri, RDFModelEnums.RDFDatatypes.XSD_QNAME); } catch { throw new RDFModelException(String.Format("found '{0}' predicate which cannot be abbreviated to a valid QName", predUri)); } XmlNode predNode = rdfDoc.CreateNode(XmlNodeType.Element, predUri, predNS.ToString()); #endregion #region object if (triple.TripleFlavor == RDFModelEnums.RDFTripleFlavors.SPO) { //If the object is a container subj, we must append its entire node saved in the containers dictionary if (containers.Keys.Any(k => k.Equals(triple.Object)) && !floatingContainers) { predNode.AppendChild(containers.Single(c => c.Key.Equals(triple.Object)).Value); } //Else, if the object is a subject of a collection of resources, we must append the "rdf:parseType=Collection" attribute to the predicate node else if (graph.GraphMetadata.Collections.Keys.Any(k => k.Equals(triple.Object)) && graph.GraphMetadata.Collections.Single(c => c.Key.Equals(triple.Object)).Value.ItemType == RDFModelEnums.RDFItemTypes.Resource && !floatingCollections) { XmlAttribute rdfParseType = rdfDoc.CreateAttribute(RDFVocabulary.RDF.PREFIX + ":parseType", RDFVocabulary.RDF.BASE_URI); XmlText rdfParseTypeText = rdfDoc.CreateTextNode("Collection"); rdfParseType.AppendChild(rdfParseTypeText); predNode.Attributes.Append(rdfParseType); //Then we append sequentially the collection elements List<XmlNode> collElements = ReconstructCollection(graph.GraphMetadata, (RDFResource)triple.Object, rdfDoc); collElements.ForEach(c => predNode.AppendChild(c)); } //Else, threat it as a traditional object node else { String objString = triple.Object.ToString(); XmlAttribute predNodeDesc = null; XmlText predNodeDescText = rdfDoc.CreateTextNode(objString); // rdf:nodeID="blankID"> if (objString.StartsWith("bnode:")) { predNodeDesc = rdfDoc.CreateAttribute(RDFVocabulary.RDF.PREFIX + ":nodeID", RDFVocabulary.RDF.BASE_URI); } // rdf:resource="objURI"> else { predNodeDesc = rdfDoc.CreateAttribute(RDFVocabulary.RDF.PREFIX + ":resource", RDFVocabulary.RDF.BASE_URI); } predNodeDesc.AppendChild(predNodeDescText); predNode.Attributes.Append(predNodeDesc); } } #endregion #region literal else { #region plain literal if (triple.Object is RDFPlainLiteral) { RDFPlainLiteral pLit = (RDFPlainLiteral)triple.Object; // xml:lang="plitLANG"> if (pLit.Language != String.Empty) { XmlAttribute plainLiteralLangNodeDesc = rdfDoc.CreateAttribute(RDFVocabulary.XML.PREFIX + ":lang", RDFVocabulary.XML.BASE_URI); XmlText plainLiteralLangNodeDescText = rdfDoc.CreateTextNode(pLit.Language); plainLiteralLangNodeDesc.AppendChild(plainLiteralLangNodeDescText); predNode.Attributes.Append(plainLiteralLangNodeDesc); } } #endregion #region typed literal // rdf:datatype="tlitURI"> else { RDFTypedLiteral tLit = (RDFTypedLiteral)triple.Object; XmlAttribute typedLiteralNodeDesc = rdfDoc.CreateAttribute(RDFVocabulary.RDF.PREFIX + ":datatype", RDFVocabulary.RDF.BASE_URI); XmlText typedLiteralNodeDescText = rdfDoc.CreateTextNode(RDFModelUtilities.GetDatatypeFromEnum(tLit.Datatype)); typedLiteralNodeDesc.AppendChild(typedLiteralNodeDescText); predNode.Attributes.Append(typedLiteralNodeDesc); } #endregion //litVALUE</predPREF:predURI>" XmlText litNodeDescText = rdfDoc.CreateTextNode(RDFModelUtilities.EscapeControlCharsForXML(HttpUtility.HtmlDecode(((RDFLiteral)triple.Object).Value))); predNode.AppendChild(litNodeDescText); } #endregion subjNode.AppendChild(predNode); } } //Raw containers must not be written as-is, instead they have to be saved //and attached when their subj is found later as object of a triple if (!subjNode.Name.Equals(RDFVocabulary.RDF.PREFIX + ":Bag", StringComparison.Ordinal) && !subjNode.Name.Equals(RDFVocabulary.RDF.PREFIX + ":Seq", StringComparison.Ordinal) && !subjNode.Name.Equals(RDFVocabulary.RDF.PREFIX + ":Alt", StringComparison.Ordinal)) { rdfRoot.AppendChild(subjNode); } #endregion } #endregion rdfDoc.AppendChild(rdfRoot); #endregion rdfDoc.Save(rdfxmlWriter); } #endregion } catch (Exception ex) { throw new RDFModelException("Cannot serialize RDF/Xml because: " + ex.Message, ex); } }