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;
}
Пример #2
0
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;
}