1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/rdf/base/src/nsRDFXMLSerializer.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,1126 @@ 1.4 +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- 1.5 + * vim: set ts=4 sw=4 et tw=80: 1.6 + * 1.7 + * This Source Code Form is subject to the terms of the Mozilla Public 1.8 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.9 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.10 + 1.11 +#include "nsRDFXMLSerializer.h" 1.12 + 1.13 +#include "nsIAtom.h" 1.14 +#include "nsIOutputStream.h" 1.15 +#include "nsIRDFService.h" 1.16 +#include "nsIRDFContainerUtils.h" 1.17 +#include "nsIServiceManager.h" 1.18 +#include "nsString.h" 1.19 +#include "nsXPIDLString.h" 1.20 +#include "nsTArray.h" 1.21 +#include "rdf.h" 1.22 +#include "rdfutil.h" 1.23 +#include "mozilla/Attributes.h" 1.24 + 1.25 +#include "rdfIDataSource.h" 1.26 + 1.27 +int32_t nsRDFXMLSerializer::gRefCnt = 0; 1.28 +nsIRDFContainerUtils* nsRDFXMLSerializer::gRDFC; 1.29 +nsIRDFResource* nsRDFXMLSerializer::kRDF_instanceOf; 1.30 +nsIRDFResource* nsRDFXMLSerializer::kRDF_type; 1.31 +nsIRDFResource* nsRDFXMLSerializer::kRDF_nextVal; 1.32 +nsIRDFResource* nsRDFXMLSerializer::kRDF_Bag; 1.33 +nsIRDFResource* nsRDFXMLSerializer::kRDF_Seq; 1.34 +nsIRDFResource* nsRDFXMLSerializer::kRDF_Alt; 1.35 + 1.36 +static const char kRDFDescriptionOpen[] = " <RDF:Description"; 1.37 +static const char kIDAttr[] = " RDF:ID=\""; 1.38 +static const char kAboutAttr[] = " RDF:about=\""; 1.39 +static const char kRDFDescriptionClose[] = " </RDF:Description>\n"; 1.40 +static const char kRDFResource1[] = " RDF:resource=\""; 1.41 +static const char kRDFResource2[] = "\"/>\n"; 1.42 +static const char kRDFParseTypeInteger[] = " NC:parseType=\"Integer\">"; 1.43 +static const char kRDFParseTypeDate[] = " NC:parseType=\"Date\">"; 1.44 +static const char kRDFUnknown[] = "><!-- unknown node type -->"; 1.45 + 1.46 +nsresult 1.47 +nsRDFXMLSerializer::Create(nsISupports* aOuter, REFNSIID aIID, void** aResult) 1.48 +{ 1.49 + if (aOuter) 1.50 + return NS_ERROR_NO_AGGREGATION; 1.51 + 1.52 + nsCOMPtr<nsIRDFXMLSerializer> result = new nsRDFXMLSerializer(); 1.53 + if (! result) 1.54 + return NS_ERROR_OUT_OF_MEMORY; 1.55 + // The serializer object is here, addref gRefCnt so that the 1.56 + // destructor can safely release it. 1.57 + gRefCnt++; 1.58 + 1.59 + nsresult rv; 1.60 + rv = result->QueryInterface(aIID, aResult); 1.61 + 1.62 + if (NS_FAILED(rv)) return rv; 1.63 + 1.64 + if (gRefCnt == 1) do { 1.65 + nsCOMPtr<nsIRDFService> rdf = do_GetService("@mozilla.org/rdf/rdf-service;1", &rv); 1.66 + if (NS_FAILED(rv)) break; 1.67 + 1.68 + rv = rdf->GetResource(NS_LITERAL_CSTRING(RDF_NAMESPACE_URI "instanceOf"), 1.69 + &kRDF_instanceOf); 1.70 + if (NS_FAILED(rv)) break; 1.71 + 1.72 + rv = rdf->GetResource(NS_LITERAL_CSTRING(RDF_NAMESPACE_URI "type"), 1.73 + &kRDF_type); 1.74 + if (NS_FAILED(rv)) break; 1.75 + 1.76 + rv = rdf->GetResource(NS_LITERAL_CSTRING(RDF_NAMESPACE_URI "nextVal"), 1.77 + &kRDF_nextVal); 1.78 + if (NS_FAILED(rv)) break; 1.79 + 1.80 + rv = rdf->GetResource(NS_LITERAL_CSTRING(RDF_NAMESPACE_URI "Bag"), 1.81 + &kRDF_Bag); 1.82 + if (NS_FAILED(rv)) break; 1.83 + 1.84 + rv = rdf->GetResource(NS_LITERAL_CSTRING(RDF_NAMESPACE_URI "Seq"), 1.85 + &kRDF_Seq); 1.86 + if (NS_FAILED(rv)) break; 1.87 + 1.88 + rv = rdf->GetResource(NS_LITERAL_CSTRING(RDF_NAMESPACE_URI "Alt"), 1.89 + &kRDF_Alt); 1.90 + if (NS_FAILED(rv)) break; 1.91 + 1.92 + rv = CallGetService("@mozilla.org/rdf/container-utils;1", &gRDFC); 1.93 + if (NS_FAILED(rv)) break; 1.94 + } while (0); 1.95 + 1.96 + return rv; 1.97 +} 1.98 + 1.99 +nsRDFXMLSerializer::nsRDFXMLSerializer() 1.100 +{ 1.101 + MOZ_COUNT_CTOR(nsRDFXMLSerializer); 1.102 +} 1.103 + 1.104 +nsRDFXMLSerializer::~nsRDFXMLSerializer() 1.105 +{ 1.106 + MOZ_COUNT_DTOR(nsRDFXMLSerializer); 1.107 + 1.108 + if (--gRefCnt == 0) { 1.109 + NS_IF_RELEASE(kRDF_Bag); 1.110 + NS_IF_RELEASE(kRDF_Seq); 1.111 + NS_IF_RELEASE(kRDF_Alt); 1.112 + NS_IF_RELEASE(kRDF_instanceOf); 1.113 + NS_IF_RELEASE(kRDF_type); 1.114 + NS_IF_RELEASE(kRDF_nextVal); 1.115 + NS_IF_RELEASE(gRDFC); 1.116 + } 1.117 +} 1.118 + 1.119 +NS_IMPL_ISUPPORTS(nsRDFXMLSerializer, nsIRDFXMLSerializer, nsIRDFXMLSource) 1.120 + 1.121 +NS_IMETHODIMP 1.122 +nsRDFXMLSerializer::Init(nsIRDFDataSource* aDataSource) 1.123 +{ 1.124 + if (! aDataSource) 1.125 + return NS_ERROR_NULL_POINTER; 1.126 + 1.127 + mDataSource = aDataSource; 1.128 + mDataSource->GetURI(getter_Copies(mBaseURLSpec)); 1.129 + 1.130 + // Add the ``RDF'' prefix, by default. 1.131 + nsCOMPtr<nsIAtom> prefix; 1.132 + 1.133 + prefix = do_GetAtom("RDF"); 1.134 + AddNameSpace(prefix, NS_LITERAL_STRING("http://www.w3.org/1999/02/22-rdf-syntax-ns#")); 1.135 + 1.136 + prefix = do_GetAtom("NC"); 1.137 + AddNameSpace(prefix, NS_LITERAL_STRING("http://home.netscape.com/NC-rdf#")); 1.138 + 1.139 + mPrefixID = 0; 1.140 + 1.141 + return NS_OK; 1.142 +} 1.143 + 1.144 +NS_IMETHODIMP 1.145 +nsRDFXMLSerializer::AddNameSpace(nsIAtom* aPrefix, const nsAString& aURI) 1.146 +{ 1.147 + nsCOMPtr<nsIAtom> prefix = aPrefix; 1.148 + if (!prefix) { 1.149 + // Make up a prefix, we don't want default namespaces, so 1.150 + // that we can use QNames for elements and attributes alike. 1.151 + prefix = EnsureNewPrefix(); 1.152 + } 1.153 + mNameSpaces.Put(aURI, prefix); 1.154 + return NS_OK; 1.155 +} 1.156 + 1.157 +static nsresult 1.158 +rdf_BlockingWrite(nsIOutputStream* stream, const char* buf, uint32_t size) 1.159 +{ 1.160 + uint32_t written = 0; 1.161 + uint32_t remaining = size; 1.162 + while (remaining > 0) { 1.163 + nsresult rv; 1.164 + uint32_t cb; 1.165 + 1.166 + if (NS_FAILED(rv = stream->Write(buf + written, remaining, &cb))) 1.167 + return rv; 1.168 + 1.169 + written += cb; 1.170 + remaining -= cb; 1.171 + } 1.172 + return NS_OK; 1.173 +} 1.174 + 1.175 +static nsresult 1.176 +rdf_BlockingWrite(nsIOutputStream* stream, const nsCSubstring& s) 1.177 +{ 1.178 + return rdf_BlockingWrite(stream, s.BeginReading(), s.Length()); 1.179 +} 1.180 + 1.181 +static nsresult 1.182 +rdf_BlockingWrite(nsIOutputStream* stream, const nsAString& s) 1.183 +{ 1.184 + NS_ConvertUTF16toUTF8 utf8(s); 1.185 + return rdf_BlockingWrite(stream, utf8.get(), utf8.Length()); 1.186 +} 1.187 + 1.188 +already_AddRefed<nsIAtom> 1.189 +nsRDFXMLSerializer::EnsureNewPrefix() 1.190 +{ 1.191 + nsAutoString qname; 1.192 + nsCOMPtr<nsIAtom> prefix; 1.193 + bool isNewPrefix; 1.194 + do { 1.195 + isNewPrefix = true; 1.196 + qname.AssignLiteral("NS"); 1.197 + qname.AppendInt(++mPrefixID, 10); 1.198 + prefix = do_GetAtom(qname); 1.199 + nsNameSpaceMap::const_iterator iter = mNameSpaces.first(); 1.200 + while (iter != mNameSpaces.last() && isNewPrefix) { 1.201 + isNewPrefix = (iter->mPrefix != prefix); 1.202 + ++iter; 1.203 + } 1.204 + } while (!isNewPrefix); 1.205 + return prefix.forget(); 1.206 +} 1.207 + 1.208 +// This converts a property resource (like 1.209 +// "http://www.w3.org/TR/WD-rdf-syntax#Description") into a QName 1.210 +// ("RDF:Description"), and registers the namespace, if it's made up. 1.211 + 1.212 +nsresult 1.213 +nsRDFXMLSerializer::RegisterQName(nsIRDFResource* aResource) 1.214 +{ 1.215 + nsAutoCString uri, qname; 1.216 + aResource->GetValueUTF8(uri); 1.217 + 1.218 + nsNameSpaceMap::const_iterator iter = mNameSpaces.GetNameSpaceOf(uri); 1.219 + if (iter != mNameSpaces.last()) { 1.220 + NS_ENSURE_TRUE(iter->mPrefix, NS_ERROR_UNEXPECTED); 1.221 + iter->mPrefix->ToUTF8String(qname); 1.222 + qname.Append(':'); 1.223 + qname += StringTail(uri, uri.Length() - iter->mURI.Length()); 1.224 + mQNames.Put(aResource, qname); 1.225 + return NS_OK; 1.226 + } 1.227 + 1.228 + // Okay, so we don't have it in our map. Try to make one up. This 1.229 + // is very bogus. 1.230 + int32_t i = uri.RFindChar('#'); // first try a '#' 1.231 + if (i == -1) { 1.232 + i = uri.RFindChar('/'); 1.233 + if (i == -1) { 1.234 + // Okay, just punt and assume there is _no_ namespace on 1.235 + // this thing... 1.236 + mQNames.Put(aResource, uri); 1.237 + return NS_OK; 1.238 + } 1.239 + } 1.240 + 1.241 + // Take whatever is to the right of the '#' or '/' and call it the 1.242 + // local name, make up a prefix. 1.243 + nsCOMPtr<nsIAtom> prefix = EnsureNewPrefix(); 1.244 + mNameSpaces.Put(StringHead(uri, i+1), prefix); 1.245 + prefix->ToUTF8String(qname); 1.246 + qname.Append(':'); 1.247 + qname += StringTail(uri, uri.Length() - (i + 1)); 1.248 + 1.249 + mQNames.Put(aResource, qname); 1.250 + return NS_OK; 1.251 +} 1.252 + 1.253 +nsresult 1.254 +nsRDFXMLSerializer::GetQName(nsIRDFResource* aResource, nsCString& aQName) 1.255 +{ 1.256 + return mQNames.Get(aResource, &aQName) ? NS_OK : NS_ERROR_UNEXPECTED; 1.257 +} 1.258 + 1.259 +bool 1.260 +nsRDFXMLSerializer::IsContainerProperty(nsIRDFResource* aProperty) 1.261 +{ 1.262 + // Return `true' if the property is an internal property related 1.263 + // to being a container. 1.264 + if (aProperty == kRDF_instanceOf) 1.265 + return true; 1.266 + 1.267 + if (aProperty == kRDF_nextVal) 1.268 + return true; 1.269 + 1.270 + bool isOrdinal = false; 1.271 + gRDFC->IsOrdinalProperty(aProperty, &isOrdinal); 1.272 + if (isOrdinal) 1.273 + return true; 1.274 + 1.275 + return false; 1.276 +} 1.277 + 1.278 + 1.279 +// convert '&', '<', and '>' into "&", "<", and ">", respectively. 1.280 +static const char amp[] = "&"; 1.281 +static const char lt[] = "<"; 1.282 +static const char gt[] = ">"; 1.283 +static const char quot[] = """; 1.284 + 1.285 +static void 1.286 +rdf_EscapeAmpersandsAndAngleBrackets(nsCString& s) 1.287 +{ 1.288 + uint32_t newLength, origLength; 1.289 + newLength = origLength = s.Length(); 1.290 + 1.291 + // Compute the length of the result string. 1.292 + const char* start = s.BeginReading(); 1.293 + const char* end = s.EndReading(); 1.294 + const char* c = start; 1.295 + while (c != end) { 1.296 + switch (*c) { 1.297 + case '&' : 1.298 + newLength += sizeof(amp) - 2; 1.299 + break; 1.300 + case '<': 1.301 + case '>': 1.302 + newLength += sizeof(gt) - 2; 1.303 + break; 1.304 + default: 1.305 + break; 1.306 + } 1.307 + ++c; 1.308 + } 1.309 + if (newLength == origLength) { 1.310 + // nothing to escape 1.311 + return; 1.312 + } 1.313 + 1.314 + // escape the chars from the end back to the front. 1.315 + s.SetLength(newLength); 1.316 + 1.317 + // Buffer might have changed, get the pointers again 1.318 + start = s.BeginReading(); // begin of string 1.319 + c = start + origLength - 1; // last char in original string 1.320 + char* w = s.EndWriting() - 1; // last char in grown buffer 1.321 + while (c >= start) { 1.322 + switch (*c) { 1.323 + case '&' : 1.324 + w -= 4; 1.325 + nsCharTraits<char>::copy(w, amp, sizeof(amp) - 1); 1.326 + break; 1.327 + case '<': 1.328 + w -= 3; 1.329 + nsCharTraits<char>::copy(w, lt, sizeof(lt) - 1); 1.330 + break; 1.331 + case '>': 1.332 + w -= 3; 1.333 + nsCharTraits<char>::copy(w, gt, sizeof(gt) - 1); 1.334 + break; 1.335 + default: 1.336 + *w = *c; 1.337 + } 1.338 + --w; 1.339 + --c; 1.340 + } 1.341 +} 1.342 + 1.343 +// convert '"' to """ 1.344 +static void 1.345 +rdf_EscapeQuotes(nsCString& s) 1.346 +{ 1.347 + int32_t i = 0; 1.348 + while ((i = s.FindChar('"', i)) != -1) { 1.349 + s.Replace(i, 1, quot, sizeof(quot) - 1); 1.350 + i += sizeof(quot) - 2; 1.351 + } 1.352 +} 1.353 + 1.354 +static void 1.355 +rdf_EscapeAttributeValue(nsCString& s) 1.356 +{ 1.357 + rdf_EscapeAmpersandsAndAngleBrackets(s); 1.358 + rdf_EscapeQuotes(s); 1.359 +} 1.360 + 1.361 + 1.362 +nsresult 1.363 +nsRDFXMLSerializer::SerializeInlineAssertion(nsIOutputStream* aStream, 1.364 + nsIRDFResource* aResource, 1.365 + nsIRDFResource* aProperty, 1.366 + nsIRDFLiteral* aValue) 1.367 +{ 1.368 + nsresult rv; 1.369 + nsCString qname; 1.370 + rv = GetQName(aProperty, qname); 1.371 + NS_ENSURE_SUCCESS(rv, rv); 1.372 + 1.373 + rv = rdf_BlockingWrite(aStream, 1.374 + NS_LITERAL_CSTRING("\n ")); 1.375 + if (NS_FAILED(rv)) return rv; 1.376 + 1.377 + const char16_t* value; 1.378 + aValue->GetValueConst(&value); 1.379 + NS_ConvertUTF16toUTF8 s(value); 1.380 + 1.381 + rdf_EscapeAttributeValue(s); 1.382 + 1.383 + rv = rdf_BlockingWrite(aStream, qname); 1.384 + if (NS_FAILED(rv)) return rv; 1.385 + rv = rdf_BlockingWrite(aStream, "=\"", 2); 1.386 + if (NS_FAILED(rv)) return rv; 1.387 + s.Append('"'); 1.388 + return rdf_BlockingWrite(aStream, s); 1.389 +} 1.390 + 1.391 +nsresult 1.392 +nsRDFXMLSerializer::SerializeChildAssertion(nsIOutputStream* aStream, 1.393 + nsIRDFResource* aResource, 1.394 + nsIRDFResource* aProperty, 1.395 + nsIRDFNode* aValue) 1.396 +{ 1.397 + nsCString qname; 1.398 + nsresult rv = GetQName(aProperty, qname); 1.399 + NS_ENSURE_SUCCESS(rv, rv); 1.400 + 1.401 + rv = rdf_BlockingWrite(aStream, " <", 5); 1.402 + if (NS_FAILED(rv)) return rv; 1.403 + rv = rdf_BlockingWrite(aStream, qname); 1.404 + if (NS_FAILED(rv)) return rv; 1.405 + 1.406 + nsCOMPtr<nsIRDFResource> resource; 1.407 + nsCOMPtr<nsIRDFLiteral> literal; 1.408 + nsCOMPtr<nsIRDFInt> number; 1.409 + nsCOMPtr<nsIRDFDate> date; 1.410 + 1.411 + if ((resource = do_QueryInterface(aValue)) != nullptr) { 1.412 + nsAutoCString uri; 1.413 + resource->GetValueUTF8(uri); 1.414 + 1.415 + rdf_MakeRelativeRef(mBaseURLSpec, uri); 1.416 + rdf_EscapeAttributeValue(uri); 1.417 + 1.418 + rv = rdf_BlockingWrite(aStream, kRDFResource1, 1.419 + sizeof(kRDFResource1) - 1); 1.420 + if (NS_FAILED(rv)) return rv; 1.421 + rv = rdf_BlockingWrite(aStream, uri); 1.422 + if (NS_FAILED(rv)) return rv; 1.423 + rv = rdf_BlockingWrite(aStream, kRDFResource2, 1.424 + sizeof(kRDFResource2) - 1); 1.425 + if (NS_FAILED(rv)) return rv; 1.426 + 1.427 + goto no_close_tag; 1.428 + } 1.429 + else if ((literal = do_QueryInterface(aValue)) != nullptr) { 1.430 + const char16_t *value; 1.431 + literal->GetValueConst(&value); 1.432 + NS_ConvertUTF16toUTF8 s(value); 1.433 + 1.434 + rdf_EscapeAmpersandsAndAngleBrackets(s); 1.435 + 1.436 + rv = rdf_BlockingWrite(aStream, ">", 1); 1.437 + if (NS_FAILED(rv)) return rv; 1.438 + rv = rdf_BlockingWrite(aStream, s); 1.439 + if (NS_FAILED(rv)) return rv; 1.440 + } 1.441 + else if ((number = do_QueryInterface(aValue)) != nullptr) { 1.442 + int32_t value; 1.443 + number->GetValue(&value); 1.444 + 1.445 + nsAutoCString n; 1.446 + n.AppendInt(value); 1.447 + 1.448 + rv = rdf_BlockingWrite(aStream, kRDFParseTypeInteger, 1.449 + sizeof(kRDFParseTypeInteger) - 1); 1.450 + if (NS_FAILED(rv)) return rv; 1.451 + rv = rdf_BlockingWrite(aStream, n); 1.452 + if (NS_FAILED(rv)) return rv; 1.453 + } 1.454 + else if ((date = do_QueryInterface(aValue)) != nullptr) { 1.455 + PRTime value; 1.456 + date->GetValue(&value); 1.457 + 1.458 + nsAutoCString s; 1.459 + rdf_FormatDate(value, s); 1.460 + 1.461 + rv = rdf_BlockingWrite(aStream, kRDFParseTypeDate, 1.462 + sizeof(kRDFParseTypeDate) - 1); 1.463 + if (NS_FAILED(rv)) return rv; 1.464 + rv = rdf_BlockingWrite(aStream, s); 1.465 + if (NS_FAILED(rv)) return rv; 1.466 + } 1.467 + else { 1.468 + // XXX it doesn't support nsIRDFResource _or_ nsIRDFLiteral??? 1.469 + // We should serialize nsIRDFInt, nsIRDFDate, etc... 1.470 + NS_WARNING("unknown RDF node type"); 1.471 + 1.472 + rv = rdf_BlockingWrite(aStream, kRDFUnknown, sizeof(kRDFUnknown) - 1); 1.473 + if (NS_FAILED(rv)) return rv; 1.474 + } 1.475 + 1.476 + rv = rdf_BlockingWrite(aStream, "</", 2); 1.477 + if (NS_FAILED(rv)) return rv; 1.478 + rv = rdf_BlockingWrite(aStream, qname); 1.479 + if (NS_FAILED(rv)) return rv; 1.480 + return rdf_BlockingWrite(aStream, ">\n", 2); 1.481 + 1.482 + no_close_tag: 1.483 + return NS_OK; 1.484 +} 1.485 + 1.486 +nsresult 1.487 +nsRDFXMLSerializer::SerializeProperty(nsIOutputStream* aStream, 1.488 + nsIRDFResource* aResource, 1.489 + nsIRDFResource* aProperty, 1.490 + bool aInline, 1.491 + int32_t* aSkipped) 1.492 +{ 1.493 + nsresult rv = NS_OK; 1.494 + 1.495 + int32_t skipped = 0; 1.496 + 1.497 + nsCOMPtr<nsISimpleEnumerator> assertions; 1.498 + mDataSource->GetTargets(aResource, aProperty, true, getter_AddRefs(assertions)); 1.499 + if (! assertions) 1.500 + return NS_ERROR_FAILURE; 1.501 + 1.502 + // Serializing the assertion inline is ok as long as the property has 1.503 + // only one target value, and it is a literal that doesn't include line 1.504 + // breaks. 1.505 + bool needsChild = false; 1.506 + 1.507 + while (1) { 1.508 + bool hasMore = false; 1.509 + assertions->HasMoreElements(&hasMore); 1.510 + if (! hasMore) 1.511 + break; 1.512 + 1.513 + nsCOMPtr<nsISupports> isupports; 1.514 + assertions->GetNext(getter_AddRefs(isupports)); 1.515 + nsCOMPtr<nsIRDFLiteral> literal = do_QueryInterface(isupports); 1.516 + needsChild |= (!literal); 1.517 + 1.518 + if (!needsChild) { 1.519 + assertions->HasMoreElements(&needsChild); 1.520 + if (!needsChild) { 1.521 + const char16_t* literalVal = nullptr; 1.522 + literal->GetValueConst(&literalVal); 1.523 + if (literalVal) { 1.524 + for (; *literalVal; literalVal++) { 1.525 + if (*literalVal == char16_t('\n') || 1.526 + *literalVal == char16_t('\r')) { 1.527 + needsChild = true; 1.528 + break; 1.529 + } 1.530 + } 1.531 + } 1.532 + } 1.533 + } 1.534 + 1.535 + if (aInline && !needsChild) { 1.536 + rv = SerializeInlineAssertion(aStream, aResource, aProperty, literal); 1.537 + } 1.538 + else if (!aInline && needsChild) { 1.539 + nsCOMPtr<nsIRDFNode> value = do_QueryInterface(isupports); 1.540 + rv = SerializeChildAssertion(aStream, aResource, aProperty, value); 1.541 + } 1.542 + else { 1.543 + ++skipped; 1.544 + rv = NS_OK; 1.545 + } 1.546 + 1.547 + if (NS_FAILED(rv)) 1.548 + break; 1.549 + } 1.550 + 1.551 + *aSkipped += skipped; 1.552 + return rv; 1.553 +} 1.554 + 1.555 + 1.556 +nsresult 1.557 +nsRDFXMLSerializer::SerializeDescription(nsIOutputStream* aStream, 1.558 + nsIRDFResource* aResource) 1.559 +{ 1.560 + nsresult rv; 1.561 + 1.562 + bool isTypedNode = false; 1.563 + nsCString typeQName; 1.564 + 1.565 + nsCOMPtr<nsIRDFNode> typeNode; 1.566 + mDataSource->GetTarget(aResource, kRDF_type, true, getter_AddRefs(typeNode)); 1.567 + if (typeNode) { 1.568 + nsCOMPtr<nsIRDFResource> type = do_QueryInterface(typeNode, &rv); 1.569 + if (type) { 1.570 + // Try to get a namespace prefix. If none is available, 1.571 + // just treat the description as if it weren't a typed node 1.572 + // after all and emit rdf:type as a normal property. This 1.573 + // seems preferable to using a bogus (invented) prefix. 1.574 + isTypedNode = NS_SUCCEEDED(GetQName(type, typeQName)); 1.575 + } 1.576 + } 1.577 + 1.578 + nsAutoCString uri; 1.579 + rv = aResource->GetValueUTF8(uri); 1.580 + if (NS_FAILED(rv)) return rv; 1.581 + 1.582 + rdf_MakeRelativeRef(mBaseURLSpec, uri); 1.583 + rdf_EscapeAttributeValue(uri); 1.584 + 1.585 + // Emit an open tag and the subject 1.586 + if (isTypedNode) { 1.587 + rv = rdf_BlockingWrite(aStream, NS_LITERAL_STRING(" <")); 1.588 + if (NS_FAILED(rv)) return rv; 1.589 + // Watch out for the default namespace! 1.590 + rv = rdf_BlockingWrite(aStream, typeQName); 1.591 + if (NS_FAILED(rv)) return rv; 1.592 + } 1.593 + else { 1.594 + rv = rdf_BlockingWrite(aStream, kRDFDescriptionOpen, 1.595 + sizeof(kRDFDescriptionOpen) - 1); 1.596 + if (NS_FAILED(rv)) return rv; 1.597 + } 1.598 + if (uri[0] == char16_t('#')) { 1.599 + uri.Cut(0, 1); 1.600 + rv = rdf_BlockingWrite(aStream, kIDAttr, sizeof(kIDAttr) - 1); 1.601 + } 1.602 + else { 1.603 + rv = rdf_BlockingWrite(aStream, kAboutAttr, sizeof(kAboutAttr) - 1); 1.604 + } 1.605 + if (NS_FAILED(rv)) return rv; 1.606 + 1.607 + uri.Append('"'); 1.608 + rv = rdf_BlockingWrite(aStream, uri); 1.609 + if (NS_FAILED(rv)) return rv; 1.610 + 1.611 + // Any value that's a literal we can write out as an inline 1.612 + // attribute on the RDF:Description 1.613 + nsAutoTArray<nsIRDFResource*, 8> visited; 1.614 + int32_t skipped = 0; 1.615 + 1.616 + nsCOMPtr<nsISimpleEnumerator> arcs; 1.617 + mDataSource->ArcLabelsOut(aResource, getter_AddRefs(arcs)); 1.618 + 1.619 + if (arcs) { 1.620 + // Don't re-serialize rdf:type later on 1.621 + if (isTypedNode) 1.622 + visited.AppendElement(kRDF_type); 1.623 + 1.624 + while (1) { 1.625 + bool hasMore = false; 1.626 + arcs->HasMoreElements(&hasMore); 1.627 + if (! hasMore) 1.628 + break; 1.629 + 1.630 + nsCOMPtr<nsISupports> isupports; 1.631 + arcs->GetNext(getter_AddRefs(isupports)); 1.632 + 1.633 + nsCOMPtr<nsIRDFResource> property = do_QueryInterface(isupports); 1.634 + if (! property) 1.635 + continue; 1.636 + 1.637 + // Ignore properties that pertain to containers; we may be 1.638 + // called from SerializeContainer() if the container resource 1.639 + // has been assigned non-container properties. 1.640 + if (IsContainerProperty(property)) 1.641 + continue; 1.642 + 1.643 + // Only serialize values for the property once. 1.644 + if (visited.Contains(property.get())) 1.645 + continue; 1.646 + 1.647 + visited.AppendElement(property.get()); 1.648 + 1.649 + SerializeProperty(aStream, aResource, property, true, &skipped); 1.650 + } 1.651 + } 1.652 + 1.653 + if (skipped) { 1.654 + // Close the RDF:Description tag. 1.655 + rv = rdf_BlockingWrite(aStream, NS_LITERAL_CSTRING(">\n")); 1.656 + if (NS_FAILED(rv)) return rv; 1.657 + 1.658 + // Now write out resources (which might have their own 1.659 + // substructure) as children. 1.660 + mDataSource->ArcLabelsOut(aResource, getter_AddRefs(arcs)); 1.661 + 1.662 + if (arcs) { 1.663 + // Forget that we've visited anything 1.664 + visited.Clear(); 1.665 + // ... except for rdf:type 1.666 + if (isTypedNode) 1.667 + visited.AppendElement(kRDF_type); 1.668 + 1.669 + while (1) { 1.670 + bool hasMore = false; 1.671 + arcs->HasMoreElements(&hasMore); 1.672 + if (! hasMore) 1.673 + break; 1.674 + 1.675 + nsCOMPtr<nsISupports> isupports; 1.676 + arcs->GetNext(getter_AddRefs(isupports)); 1.677 + 1.678 + nsCOMPtr<nsIRDFResource> property = do_QueryInterface(isupports); 1.679 + if (! property) 1.680 + continue; 1.681 + 1.682 + // Ignore properties that pertain to containers; we may be 1.683 + // called from SerializeContainer() if the container 1.684 + // resource has been assigned non-container properties. 1.685 + if (IsContainerProperty(property)) 1.686 + continue; 1.687 + 1.688 + // have we already seen this property? If so, don't write it 1.689 + // out again; serialize property will write each instance. 1.690 + if (visited.Contains(property.get())) 1.691 + continue; 1.692 + 1.693 + visited.AppendElement(property.get()); 1.694 + 1.695 + SerializeProperty(aStream, aResource, property, false, &skipped); 1.696 + } 1.697 + } 1.698 + 1.699 + // Emit a proper close-tag. 1.700 + if (isTypedNode) { 1.701 + rv = rdf_BlockingWrite(aStream, NS_LITERAL_CSTRING(" </")); 1.702 + if (NS_FAILED(rv)) return rv; 1.703 + // Watch out for the default namespace! 1.704 + rdf_BlockingWrite(aStream, typeQName); 1.705 + if (NS_FAILED(rv)) return rv; 1.706 + rdf_BlockingWrite(aStream, ">\n", 2); 1.707 + if (NS_FAILED(rv)) return rv; 1.708 + } 1.709 + else { 1.710 + rv = rdf_BlockingWrite(aStream, kRDFDescriptionClose, 1.711 + sizeof(kRDFDescriptionClose) - 1); 1.712 + if (NS_FAILED(rv)) return rv; 1.713 + } 1.714 + } 1.715 + else { 1.716 + // If we saw _no_ child properties, then we can don't need a 1.717 + // close-tag. 1.718 + rv = rdf_BlockingWrite(aStream, NS_LITERAL_CSTRING(" />\n")); 1.719 + if (NS_FAILED(rv)) return rv; 1.720 + } 1.721 + 1.722 + return NS_OK; 1.723 +} 1.724 + 1.725 +nsresult 1.726 +nsRDFXMLSerializer::SerializeMember(nsIOutputStream* aStream, 1.727 + nsIRDFResource* aContainer, 1.728 + nsIRDFNode* aMember) 1.729 +{ 1.730 + // If it's a resource, then output a "<RDF:li RDF:resource=... />" 1.731 + // tag, because we'll be dumping the resource separately. (We 1.732 + // iterate thru all the resources in the datasource, 1.733 + // remember?) Otherwise, output the literal value. 1.734 + 1.735 + nsCOMPtr<nsIRDFResource> resource; 1.736 + nsCOMPtr<nsIRDFLiteral> literal; 1.737 + nsCOMPtr<nsIRDFInt> number; 1.738 + nsCOMPtr<nsIRDFDate> date; 1.739 + 1.740 +static const char kRDFLIOpen[] = " <RDF:li"; 1.741 + nsresult rv = rdf_BlockingWrite(aStream, kRDFLIOpen, 1.742 + sizeof(kRDFLIOpen) - 1); 1.743 + if (NS_FAILED(rv)) return rv; 1.744 + 1.745 + if ((resource = do_QueryInterface(aMember)) != nullptr) { 1.746 + nsAutoCString uri; 1.747 + resource->GetValueUTF8(uri); 1.748 + 1.749 + rdf_MakeRelativeRef(mBaseURLSpec, uri); 1.750 + rdf_EscapeAttributeValue(uri); 1.751 + 1.752 + rv = rdf_BlockingWrite(aStream, kRDFResource1, 1.753 + sizeof(kRDFResource1) - 1); 1.754 + if (NS_FAILED(rv)) return rv; 1.755 + rv = rdf_BlockingWrite(aStream, uri); 1.756 + if (NS_FAILED(rv)) return rv; 1.757 + rv = rdf_BlockingWrite(aStream, kRDFResource2, 1.758 + sizeof(kRDFResource2) - 1); 1.759 + if (NS_FAILED(rv)) return rv; 1.760 + 1.761 + goto no_close_tag; 1.762 + } 1.763 + else if ((literal = do_QueryInterface(aMember)) != nullptr) { 1.764 + const char16_t *value; 1.765 + literal->GetValueConst(&value); 1.766 +static const char kRDFLIOpenGT[] = ">"; 1.767 + // close the '<RDF:LI' before adding the literal 1.768 + rv = rdf_BlockingWrite(aStream, kRDFLIOpenGT, 1.769 + sizeof(kRDFLIOpenGT) - 1); 1.770 + if (NS_FAILED(rv)) return rv; 1.771 + 1.772 + NS_ConvertUTF16toUTF8 s(value); 1.773 + rdf_EscapeAmpersandsAndAngleBrackets(s); 1.774 + 1.775 + rv = rdf_BlockingWrite(aStream, s); 1.776 + if (NS_FAILED(rv)) return rv; 1.777 + } 1.778 + else if ((number = do_QueryInterface(aMember)) != nullptr) { 1.779 + int32_t value; 1.780 + number->GetValue(&value); 1.781 + 1.782 + nsAutoCString n; 1.783 + n.AppendInt(value); 1.784 + 1.785 + rv = rdf_BlockingWrite(aStream, kRDFParseTypeInteger, 1.786 + sizeof(kRDFParseTypeInteger) - 1); 1.787 + if (NS_FAILED(rv)) return rv; 1.788 + rv = rdf_BlockingWrite(aStream, n); 1.789 + if (NS_FAILED(rv)) return rv; 1.790 + } 1.791 + else if ((date = do_QueryInterface(aMember)) != nullptr) { 1.792 + PRTime value; 1.793 + date->GetValue(&value); 1.794 + 1.795 + nsAutoCString s; 1.796 + rdf_FormatDate(value, s); 1.797 + 1.798 + rv = rdf_BlockingWrite(aStream, kRDFParseTypeDate, 1.799 + sizeof(kRDFParseTypeDate) - 1); 1.800 + if (NS_FAILED(rv)) return rv; 1.801 + rv = rdf_BlockingWrite(aStream, s); 1.802 + if (NS_FAILED(rv)) return rv; 1.803 + } 1.804 + else { 1.805 + // XXX it doesn't support nsIRDFResource _or_ nsIRDFLiteral??? 1.806 + // We should serialize nsIRDFInt, nsIRDFDate, etc... 1.807 + NS_WARNING("unknown RDF node type"); 1.808 + 1.809 + rv = rdf_BlockingWrite(aStream, kRDFUnknown, sizeof(kRDFUnknown) - 1); 1.810 + if (NS_FAILED(rv)) return rv; 1.811 + } 1.812 + 1.813 + { 1.814 +static const char kRDFLIClose[] = "</RDF:li>\n"; 1.815 + rv = rdf_BlockingWrite(aStream, kRDFLIClose, sizeof(kRDFLIClose) - 1); 1.816 + if (NS_FAILED(rv)) return rv; 1.817 + } 1.818 + 1.819 + no_close_tag: 1.820 + return NS_OK; 1.821 +} 1.822 + 1.823 + 1.824 +nsresult 1.825 +nsRDFXMLSerializer::SerializeContainer(nsIOutputStream* aStream, 1.826 + nsIRDFResource* aContainer) 1.827 +{ 1.828 + nsresult rv; 1.829 + nsAutoCString tag; 1.830 + 1.831 + // Decide if it's a sequence, bag, or alternation, and print the 1.832 + // appropriate tag-open sequence 1.833 + 1.834 + if (IsA(mDataSource, aContainer, kRDF_Bag)) { 1.835 + tag.AssignLiteral("RDF:Bag"); 1.836 + } 1.837 + else if (IsA(mDataSource, aContainer, kRDF_Seq)) { 1.838 + tag.AssignLiteral("RDF:Seq"); 1.839 + } 1.840 + else if (IsA(mDataSource, aContainer, kRDF_Alt)) { 1.841 + tag.AssignLiteral("RDF:Alt"); 1.842 + } 1.843 + else { 1.844 + NS_ASSERTION(false, "huh? this is _not_ a container."); 1.845 + return NS_ERROR_UNEXPECTED; 1.846 + } 1.847 + 1.848 + rv = rdf_BlockingWrite(aStream, " <", 3); 1.849 + if (NS_FAILED(rv)) return rv; 1.850 + rv = rdf_BlockingWrite(aStream, tag); 1.851 + if (NS_FAILED(rv)) return rv; 1.852 + 1.853 + 1.854 + // Unfortunately, we always need to print out the identity of the 1.855 + // resource, even if was constructed "anonymously". We need to do 1.856 + // this because we never really know who else might be referring 1.857 + // to it... 1.858 + 1.859 + nsAutoCString uri; 1.860 + if (NS_SUCCEEDED(aContainer->GetValueUTF8(uri))) { 1.861 + rdf_MakeRelativeRef(mBaseURLSpec, uri); 1.862 + 1.863 + rdf_EscapeAttributeValue(uri); 1.864 + 1.865 + if (uri.First() == '#') { 1.866 + // Okay, it's actually identified as an element in the 1.867 + // current document, not trying to decorate some absolute 1.868 + // URI. We can use the 'ID=' attribute... 1.869 + 1.870 + uri.Cut(0, 1); // chop the '#' 1.871 + rv = rdf_BlockingWrite(aStream, kIDAttr, sizeof(kIDAttr) - 1); 1.872 + if (NS_FAILED(rv)) return rv; 1.873 + } 1.874 + else { 1.875 + // We need to cheat and spit out an illegal 'about=' on 1.876 + // the sequence. 1.877 + rv = rdf_BlockingWrite(aStream, kAboutAttr, 1.878 + sizeof(kAboutAttr) - 1); 1.879 + if (NS_FAILED(rv)) return rv; 1.880 + } 1.881 + 1.882 + rv = rdf_BlockingWrite(aStream, uri); 1.883 + if (NS_FAILED(rv)) return rv; 1.884 + rv = rdf_BlockingWrite(aStream, "\"", 1); 1.885 + if (NS_FAILED(rv)) return rv; 1.886 + } 1.887 + 1.888 + rv = rdf_BlockingWrite(aStream, ">\n", 2); 1.889 + if (NS_FAILED(rv)) return rv; 1.890 + 1.891 + // First iterate through each of the ordinal elements (the RDF/XML 1.892 + // syntax doesn't allow us to place properties on RDF container 1.893 + // elements). 1.894 + nsCOMPtr<nsISimpleEnumerator> elements; 1.895 + rv = NS_NewContainerEnumerator(mDataSource, aContainer, getter_AddRefs(elements)); 1.896 + 1.897 + if (NS_SUCCEEDED(rv)) { 1.898 + while (1) { 1.899 + bool hasMore; 1.900 + rv = elements->HasMoreElements(&hasMore); 1.901 + if (NS_FAILED(rv)) break; 1.902 + 1.903 + if (! hasMore) 1.904 + break; 1.905 + 1.906 + nsCOMPtr<nsISupports> isupports; 1.907 + elements->GetNext(getter_AddRefs(isupports)); 1.908 + 1.909 + nsCOMPtr<nsIRDFNode> element = do_QueryInterface(isupports); 1.910 + NS_ASSERTION(element != nullptr, "not an nsIRDFNode"); 1.911 + if (! element) 1.912 + continue; 1.913 + 1.914 + SerializeMember(aStream, aContainer, element); 1.915 + } 1.916 + } 1.917 + 1.918 + // close the container tag 1.919 + rv = rdf_BlockingWrite(aStream, " </", 4); 1.920 + if (NS_FAILED(rv)) return rv; 1.921 + tag.Append(">\n", 2); 1.922 + rv = rdf_BlockingWrite(aStream, tag); 1.923 + if (NS_FAILED(rv)) return rv; 1.924 + 1.925 + // Now, we iterate through _all_ of the arcs, in case someone has 1.926 + // applied properties to the bag itself. These'll be placed in a 1.927 + // separate RDF:Description element. 1.928 + nsCOMPtr<nsISimpleEnumerator> arcs; 1.929 + mDataSource->ArcLabelsOut(aContainer, getter_AddRefs(arcs)); 1.930 + 1.931 + bool wroteDescription = false; 1.932 + while (! wroteDescription) { 1.933 + bool hasMore = false; 1.934 + rv = arcs->HasMoreElements(&hasMore); 1.935 + if (NS_FAILED(rv)) break; 1.936 + 1.937 + if (! hasMore) 1.938 + break; 1.939 + 1.940 + nsIRDFResource* property; 1.941 + rv = arcs->GetNext((nsISupports**) &property); 1.942 + if (NS_FAILED(rv)) break; 1.943 + 1.944 + // If it's a membership property, then output a "LI" 1.945 + // tag. Otherwise, output a property. 1.946 + if (! IsContainerProperty(property)) { 1.947 + rv = SerializeDescription(aStream, aContainer); 1.948 + wroteDescription = true; 1.949 + } 1.950 + 1.951 + NS_RELEASE(property); 1.952 + if (NS_FAILED(rv)) 1.953 + break; 1.954 + } 1.955 + 1.956 + return NS_OK; 1.957 +} 1.958 + 1.959 + 1.960 +nsresult 1.961 +nsRDFXMLSerializer::SerializePrologue(nsIOutputStream* aStream) 1.962 +{ 1.963 +static const char kXMLVersion[] = "<?xml version=\"1.0\"?>\n"; 1.964 + 1.965 + nsresult rv; 1.966 + rv = rdf_BlockingWrite(aStream, kXMLVersion, sizeof(kXMLVersion) - 1); 1.967 + if (NS_FAILED(rv)) return rv; 1.968 + 1.969 + // global name space declarations 1.970 + rv = rdf_BlockingWrite(aStream, NS_LITERAL_CSTRING("<RDF:RDF ")); 1.971 + if (NS_FAILED(rv)) return rv; 1.972 + 1.973 + nsNameSpaceMap::const_iterator first = mNameSpaces.first(); 1.974 + nsNameSpaceMap::const_iterator last = mNameSpaces.last(); 1.975 + for (nsNameSpaceMap::const_iterator entry = first; entry != last; ++entry) { 1.976 + if (entry != first) { 1.977 + rv = rdf_BlockingWrite(aStream, NS_LITERAL_CSTRING("\n ")); 1.978 + if (NS_FAILED(rv)) return rv; 1.979 + } 1.980 + rv = rdf_BlockingWrite(aStream, NS_LITERAL_CSTRING("xmlns")); 1.981 + if (NS_FAILED(rv)) return rv; 1.982 + 1.983 + if (entry->mPrefix) { 1.984 + rv = rdf_BlockingWrite(aStream, NS_LITERAL_CSTRING(":")); 1.985 + if (NS_FAILED(rv)) return rv; 1.986 + nsAutoCString prefix; 1.987 + entry->mPrefix->ToUTF8String(prefix); 1.988 + rv = rdf_BlockingWrite(aStream, prefix); 1.989 + if (NS_FAILED(rv)) return rv; 1.990 + } 1.991 + 1.992 + rv = rdf_BlockingWrite(aStream, NS_LITERAL_CSTRING("=\"")); 1.993 + if (NS_FAILED(rv)) return rv; 1.994 + nsAutoCString uri(entry->mURI); 1.995 + rdf_EscapeAttributeValue(uri); 1.996 + rv = rdf_BlockingWrite(aStream, uri); 1.997 + if (NS_FAILED(rv)) return rv; 1.998 + rv = rdf_BlockingWrite(aStream, NS_LITERAL_CSTRING("\"")); 1.999 + if (NS_FAILED(rv)) return rv; 1.1000 + } 1.1001 + 1.1002 + return rdf_BlockingWrite(aStream, NS_LITERAL_CSTRING(">\n")); 1.1003 +} 1.1004 + 1.1005 + 1.1006 +nsresult 1.1007 +nsRDFXMLSerializer::SerializeEpilogue(nsIOutputStream* aStream) 1.1008 +{ 1.1009 + return rdf_BlockingWrite(aStream, NS_LITERAL_CSTRING("</RDF:RDF>\n")); 1.1010 +} 1.1011 + 1.1012 +class QNameCollector MOZ_FINAL : public rdfITripleVisitor { 1.1013 +public: 1.1014 + NS_DECL_ISUPPORTS 1.1015 + NS_DECL_RDFITRIPLEVISITOR 1.1016 + QNameCollector(nsRDFXMLSerializer* aParent) 1.1017 + : mParent(aParent){} 1.1018 +private: 1.1019 + nsRDFXMLSerializer* mParent; 1.1020 +}; 1.1021 + 1.1022 +NS_IMPL_ISUPPORTS(QNameCollector, rdfITripleVisitor) 1.1023 +nsresult 1.1024 +QNameCollector::Visit(nsIRDFNode* aSubject, nsIRDFResource* aPredicate, 1.1025 + nsIRDFNode* aObject, bool aTruthValue) 1.1026 +{ 1.1027 + if (aPredicate == mParent->kRDF_type) { 1.1028 + // try to get a type QName for aObject, should be a resource 1.1029 + nsCOMPtr<nsIRDFResource> resType = do_QueryInterface(aObject); 1.1030 + if (!resType) { 1.1031 + // ignore error 1.1032 + return NS_OK; 1.1033 + } 1.1034 + if (mParent->mQNames.Get(resType, nullptr)) { 1.1035 + return NS_OK; 1.1036 + } 1.1037 + mParent->RegisterQName(resType); 1.1038 + return NS_OK; 1.1039 + } 1.1040 + 1.1041 + if (mParent->mQNames.Get(aPredicate, nullptr)) { 1.1042 + return NS_OK; 1.1043 + } 1.1044 + if (aPredicate == mParent->kRDF_instanceOf || 1.1045 + aPredicate == mParent->kRDF_nextVal) 1.1046 + return NS_OK; 1.1047 + bool isOrdinal = false; 1.1048 + mParent->gRDFC->IsOrdinalProperty(aPredicate, &isOrdinal); 1.1049 + if (isOrdinal) 1.1050 + return NS_OK; 1.1051 + 1.1052 + mParent->RegisterQName(aPredicate); 1.1053 + 1.1054 + return NS_OK; 1.1055 +} 1.1056 + 1.1057 +nsresult 1.1058 +nsRDFXMLSerializer::CollectNamespaces() 1.1059 +{ 1.1060 + // Iterate over all Triples to get namespaces for subject resource types 1.1061 + // and Predicates and cache all the QNames we want to use. 1.1062 + nsCOMPtr<rdfITripleVisitor> collector = 1.1063 + new QNameCollector(this); 1.1064 + nsCOMPtr<rdfIDataSource> ds = do_QueryInterface(mDataSource); // XXX API 1.1065 + NS_ENSURE_TRUE(collector && ds, NS_ERROR_FAILURE); 1.1066 + return ds->VisitAllTriples(collector); 1.1067 +} 1.1068 + 1.1069 +//---------------------------------------------------------------------- 1.1070 + 1.1071 +NS_IMETHODIMP 1.1072 +nsRDFXMLSerializer::Serialize(nsIOutputStream* aStream) 1.1073 +{ 1.1074 + nsresult rv; 1.1075 + 1.1076 + rv = CollectNamespaces(); 1.1077 + if (NS_FAILED(rv)) return rv; 1.1078 + 1.1079 + nsCOMPtr<nsISimpleEnumerator> resources; 1.1080 + rv = mDataSource->GetAllResources(getter_AddRefs(resources)); 1.1081 + if (NS_FAILED(rv)) return rv; 1.1082 + 1.1083 + rv = SerializePrologue(aStream); 1.1084 + if (NS_FAILED(rv)) 1.1085 + return rv; 1.1086 + 1.1087 + while (1) { 1.1088 + bool hasMore = false; 1.1089 + resources->HasMoreElements(&hasMore); 1.1090 + if (! hasMore) 1.1091 + break; 1.1092 + 1.1093 + nsCOMPtr<nsISupports> isupports; 1.1094 + resources->GetNext(getter_AddRefs(isupports)); 1.1095 + 1.1096 + nsCOMPtr<nsIRDFResource> resource = do_QueryInterface(isupports); 1.1097 + if (! resource) 1.1098 + continue; 1.1099 + 1.1100 + if (IsA(mDataSource, resource, kRDF_Bag) || 1.1101 + IsA(mDataSource, resource, kRDF_Seq) || 1.1102 + IsA(mDataSource, resource, kRDF_Alt)) { 1.1103 + rv = SerializeContainer(aStream, resource); 1.1104 + } 1.1105 + else { 1.1106 + rv = SerializeDescription(aStream, resource); 1.1107 + } 1.1108 + 1.1109 + if (NS_FAILED(rv)) 1.1110 + break; 1.1111 + } 1.1112 + 1.1113 + rv = SerializeEpilogue(aStream); 1.1114 + 1.1115 + return rv; 1.1116 +} 1.1117 + 1.1118 + 1.1119 +bool 1.1120 +nsRDFXMLSerializer::IsA(nsIRDFDataSource* aDataSource, nsIRDFResource* aResource, nsIRDFResource* aType) 1.1121 +{ 1.1122 + nsresult rv; 1.1123 + 1.1124 + bool result; 1.1125 + rv = aDataSource->HasAssertion(aResource, kRDF_instanceOf, aType, true, &result); 1.1126 + if (NS_FAILED(rv)) return false; 1.1127 + 1.1128 + return result; 1.1129 +}