NS_IMETHODIMP nsRDFXMLSerializer::Serialize(nsIOutputStream* aStream) { nsresult rv; NS_TIMELINE_START_TIMER("rdf/xml-ser"); rv = CollectNamespaces(); if (NS_FAILED(rv)) return rv; nsCOMPtr<nsISimpleEnumerator> resources; rv = mDataSource->GetAllResources(getter_AddRefs(resources)); if (NS_FAILED(rv)) return rv; rv = SerializePrologue(aStream); if (NS_FAILED(rv)) return rv; while (1) { PRBool hasMore = PR_FALSE; resources->HasMoreElements(&hasMore); if (! hasMore) break; nsCOMPtr<nsISupports> isupports; resources->GetNext(getter_AddRefs(isupports)); nsCOMPtr<nsIRDFResource> resource = do_QueryInterface(isupports); if (! resource) continue; if (IsA(mDataSource, resource, kRDF_Bag) || IsA(mDataSource, resource, kRDF_Seq) || IsA(mDataSource, resource, kRDF_Alt)) { rv = SerializeContainer(aStream, resource); } else { rv = SerializeDescription(aStream, resource); } if (NS_FAILED(rv)) break; } rv = SerializeEpilogue(aStream); NS_TIMELINE_STOP_TIMER("rdf/xml-ser"); NS_TIMELINE_MARK("rdf/xml-ser"); return rv; }
nsresult nsRDFXMLSerializer::SerializeContainer(nsIOutputStream* aStream, nsIRDFResource* aContainer) { nsresult rv; nsAutoCString tag; // Decide if it's a sequence, bag, or alternation, and print the // appropriate tag-open sequence if (IsA(mDataSource, aContainer, kRDF_Bag)) { tag.AssignLiteral("RDF:Bag"); } else if (IsA(mDataSource, aContainer, kRDF_Seq)) { tag.AssignLiteral("RDF:Seq"); } else if (IsA(mDataSource, aContainer, kRDF_Alt)) { tag.AssignLiteral("RDF:Alt"); } else { NS_ASSERTION(false, "huh? this is _not_ a container."); return NS_ERROR_UNEXPECTED; } rv = rdf_BlockingWrite(aStream, " <", 3); if (NS_FAILED(rv)) return rv; rv = rdf_BlockingWrite(aStream, tag); if (NS_FAILED(rv)) return rv; // Unfortunately, we always need to print out the identity of the // resource, even if was constructed "anonymously". We need to do // this because we never really know who else might be referring // to it... nsAutoCString uri; if (NS_SUCCEEDED(aContainer->GetValueUTF8(uri))) { rdf_MakeRelativeRef(mBaseURLSpec, uri); rdf_EscapeAttributeValue(uri); if (uri.First() == '#') { // Okay, it's actually identified as an element in the // current document, not trying to decorate some absolute // URI. We can use the 'ID=' attribute... uri.Cut(0, 1); // chop the '#' rv = rdf_BlockingWrite(aStream, kIDAttr, sizeof(kIDAttr) - 1); if (NS_FAILED(rv)) return rv; } else { // We need to cheat and spit out an illegal 'about=' on // the sequence. rv = rdf_BlockingWrite(aStream, kAboutAttr, sizeof(kAboutAttr) - 1); if (NS_FAILED(rv)) return rv; } rv = rdf_BlockingWrite(aStream, uri); if (NS_FAILED(rv)) return rv; rv = rdf_BlockingWrite(aStream, "\"", 1); if (NS_FAILED(rv)) return rv; } rv = rdf_BlockingWrite(aStream, ">\n", 2); if (NS_FAILED(rv)) return rv; // First iterate through each of the ordinal elements (the RDF/XML // syntax doesn't allow us to place properties on RDF container // elements). nsCOMPtr<nsISimpleEnumerator> elements; rv = NS_NewContainerEnumerator(mDataSource, aContainer, getter_AddRefs(elements)); if (NS_SUCCEEDED(rv)) { while (1) { bool hasMore; rv = elements->HasMoreElements(&hasMore); if (NS_FAILED(rv)) break; if (! hasMore) break; nsCOMPtr<nsISupports> isupports; elements->GetNext(getter_AddRefs(isupports)); nsCOMPtr<nsIRDFNode> element = do_QueryInterface(isupports); NS_ASSERTION(element != nullptr, "not an nsIRDFNode"); if (! element) continue; SerializeMember(aStream, aContainer, element); } } // close the container tag rv = rdf_BlockingWrite(aStream, " </", 4); if (NS_FAILED(rv)) return rv; tag.Append(">\n", 2); rv = rdf_BlockingWrite(aStream, tag); if (NS_FAILED(rv)) return rv; // Now, we iterate through _all_ of the arcs, in case someone has // applied properties to the bag itself. These'll be placed in a // separate RDF:Description element. nsCOMPtr<nsISimpleEnumerator> arcs; mDataSource->ArcLabelsOut(aContainer, getter_AddRefs(arcs)); bool wroteDescription = false; while (! wroteDescription) { bool hasMore = false; rv = arcs->HasMoreElements(&hasMore); if (NS_FAILED(rv)) break; if (! hasMore) break; nsIRDFResource* property; rv = arcs->GetNext((nsISupports**) &property); if (NS_FAILED(rv)) break; // If it's a membership property, then output a "LI" // tag. Otherwise, output a property. if (! IsContainerProperty(property)) { rv = SerializeDescription(aStream, aContainer); wroteDescription = true; } NS_RELEASE(property); if (NS_FAILED(rv)) break; } return NS_OK; }