Use the SDL LiveContent Architect API to download the output of a Publication

How do you use the SDL LiveContent Architect API to download the output of a Publication? 

For example, I want to publish a CHM file of a Publication and then download the output.

I can't seem to find any class or method that will do this. 

Thanks,

Pat

Parents
  • Hi,

    You can't. It is not implemented in web services API.

    Suppose you have a publication:

    • identifier: GUID-75CD4383-F94E-49AA-8182-9776535F8522
    • version: 1
    • format: PDF (A5 Booklet)

    You can query the MetaDataAssist2.0 > GetLOVValues [deprecated], the list you are looking for is normally called DOUTPUTFORMATNAME.

    You can query the metadata of this object with PublicationOutput2.5 > GetMetaData, and you'd get back something like:

    <ishobjects>
       <ishobject
          ishref="GUID-75CD4383-F94E-49AA-8182-9776535F8522"
          ishtype="ISHPublication" ishlogicalref="7025"
          ishversionref="7028" ishlngref="7029"/>
    </ishobjects>
    

    Grab the ishlngref attribute's value and use PublicationOutput2.5 > GetDataObjectInfoByIshLngRef to get information on that. You get back something like:

    <ishdataobjects>
       <ishdataobject ishlngref="7029" ishdataref="7030"
          ed="GUID-450AE758-34F0-4F6A-8A34-23FDCADF931C"
          edt="EDTPDF" size="3195659"
          mimetype="application/pdf" fileextension="pdf"/>
    </ishdataobjects>
    

    I guess the ed attribute is the same as psEdGUID in PublicationOutput2.5 > GetDataObjectByIshLngRef, which could be used to fetch the blob. Except this function call is billed as "internal" and it clearly says that it is " not implemented in the InfoShare webservices".

    Sorry.

    HTH

    Joakim

  • Patrick, you can absolutely download publication output using the web services API. In which language are you developing -- .NET, Java, or something else?
  • If I may, can we have the solution in Python. Otherwise I am sure the solution will be easily portable to any language once the principle is shown.
  • There is example code available in C# online. A couple of months ago we released a PowerShell business automation library on SDL's open source corner, see https://sdl.github.io/#dita It is called ISHRemote where the classic ISH prefix refers to Knowledge Center Content Manager's code name 'InfoShare'.

    As you can read on github.com/.../, ISHRemote is a PowerShell module on SDL Knowledge Center Content Manager. Its goal is business automation on top of the Component Content Management System (InfoShare). This library is constructed close to the "Web Services API" to:

    • allow business logic automation ranging from triggering publishing into the continuous integration pipeline over legacy data correction up to provisioning
    • show case code examples and API best practices

    So the library allows you to automate using the PowerShell language and is available on www.powershellgallery.com/.../ Most of it is written in C# where probably the following implementations of cmdlet's ProcessRecord function could inspire you for this thread
    A) github.com/.../PublishIshPublicationOutput.cs
    B) github.com/.../GetIshPublicationOutputData.cs

  • , a python sample might not be an easy task. The web services depend on SOAP based protocol named WS-Trust that drives the federated authentication. I would recommend the proposed solution by below.
  • I have a Python package the implements the lion's share of SDL KCCM API calls. SOAP is handled by Suds module.

    Now, going forward, as regards authentication that is a bit of a headache for sure - I have not had time to look into it in great detail yet, but it was quick to see that it will be either hard or impossible in Python. Which would be a shame.
  • quick question. Does it consume the .asmx or .svc endpoints. If .amsx is the answer then this is the older version of the endpoints that doesn't support federated authentication. The .svc are the newer version and the ones that can accept token from any compatible STS. If your solution targets the .svc endpoints, then I'm very curious to look at.
  • It consumes .asmx (and this is the last product release where that will be supposed, IIRC). So, that is the problem.

    If I get it to work with .svc I will post about it here.
  • Unfortunately, Python is not my strong suit. I program mostly in java and C#. The java code is fairly extensive in detail. I can send some code samples directly to you if needed, but I've listed the basic logic below. The basic API calls, btw, are the same regardless of asmx vs. svc, though obviously the authentication bits are different.

    1.) Call PublicationOutput25.GetMetaData to get metadata for the publication.
    (You will need to send the authorization context, publication GUID, language combination, output format name, publication version, and requested metadata (can be empty))

    docs.sdl.com/.../pub.xql

    2.) Parse the xml returned from the GetMetaData call

    Get the value of ishobject[@ishlngref]

    3.) Call PublicationOutput25.GetDataObjectInfoByIshLngRef
    (You will need to send the authorization context, and the lngref that you obtained in step 2 above)

    https://docs.sdl.com/LiveContent/web/pub.xql?action=home&pub=SDL%20Knowledge%20Center%20full%20documentation-v2.1.2&lang=en-US#docid=GUID-B3A0D845-D992-444D-B1CE-4267CDA0A865&addHistory=true&query=GetDataObjectInfoByIshLngRef&scope=&tid=b6741009-bdf0-49d7-b047-35445d0af6a2&filename=GUID-B3A0D845-D992-444D-B1CE-4267CDA0A865.xml&resource=&inner_id=&toc=false&eventType=lcContent.loadDocGUID-B3A0D845-D992-444D-B1CE-4267CDA0A865&url=/LiveContent/web/search.xql%3Fc%3Dt%26pub%3DSDL+Knowledge+Center+full+documentation-v2.1.2%26lang%3Den-US%26action%3Dsearch%26query%3DGetDataObjectInfoByIshLngRef&sid=lcSearch.runSearch1481907555400&currentQuery=GetDataObjectInfoByIshLngRef&currentScope=

    4.) Parse the xml returned from the GetDataObjectInfoByIshLngRef call

    Get the following values:

    lngref = ishdataobject[@ishlngref]
    outputGUID = ishdataobject[@ed]
    size = ishdataobject[@size]

    5.) Make successive calls to getNextDataObjectChunkByIshLngRef to get the data from the blob

    docs.sdl.com/.../pub.xql

    This is the tricky part, and hard to explain. In my java code, it looks like this:

    int offsetInt = 0;
    int maxBytesInt = 200000;
    ByteArray myByteArray = new ByteArray(); // This is a special class I created to handle progressively expanding byte arrays
    while (offsetInt < size) { // The size is what you got in step 4 above
    if (offsetInt + maxBytesInt > size) {
    maxBytesInt = size - offsetInt;
    maxBytesInt++;
    }
    byte[] receivedBytes = getNextDataObjectChunkByIshLngRef(authid, lngRef, outputGUID, offsetInt, maxBytesInt); // lngRef is what you got in step 2, outputGUID is what you got in step 4
    myByteArray.add(receivedBytes, receivedBytes.length);
    offsetInt = offsetInt + receivedBytes.length;
    }

    That's pretty much it, and you can then do whatever you want with the byte stream.
    Note that sometimes the PDF byte streams can contain extra nulls that need to be trimmed off before saving out to a file.

Reply
  • Unfortunately, Python is not my strong suit. I program mostly in java and C#. The java code is fairly extensive in detail. I can send some code samples directly to you if needed, but I've listed the basic logic below. The basic API calls, btw, are the same regardless of asmx vs. svc, though obviously the authentication bits are different.

    1.) Call PublicationOutput25.GetMetaData to get metadata for the publication.
    (You will need to send the authorization context, publication GUID, language combination, output format name, publication version, and requested metadata (can be empty))

    docs.sdl.com/.../pub.xql

    2.) Parse the xml returned from the GetMetaData call

    Get the value of ishobject[@ishlngref]

    3.) Call PublicationOutput25.GetDataObjectInfoByIshLngRef
    (You will need to send the authorization context, and the lngref that you obtained in step 2 above)

    https://docs.sdl.com/LiveContent/web/pub.xql?action=home&pub=SDL%20Knowledge%20Center%20full%20documentation-v2.1.2&lang=en-US#docid=GUID-B3A0D845-D992-444D-B1CE-4267CDA0A865&addHistory=true&query=GetDataObjectInfoByIshLngRef&scope=&tid=b6741009-bdf0-49d7-b047-35445d0af6a2&filename=GUID-B3A0D845-D992-444D-B1CE-4267CDA0A865.xml&resource=&inner_id=&toc=false&eventType=lcContent.loadDocGUID-B3A0D845-D992-444D-B1CE-4267CDA0A865&url=/LiveContent/web/search.xql%3Fc%3Dt%26pub%3DSDL+Knowledge+Center+full+documentation-v2.1.2%26lang%3Den-US%26action%3Dsearch%26query%3DGetDataObjectInfoByIshLngRef&sid=lcSearch.runSearch1481907555400&currentQuery=GetDataObjectInfoByIshLngRef&currentScope=

    4.) Parse the xml returned from the GetDataObjectInfoByIshLngRef call

    Get the following values:

    lngref = ishdataobject[@ishlngref]
    outputGUID = ishdataobject[@ed]
    size = ishdataobject[@size]

    5.) Make successive calls to getNextDataObjectChunkByIshLngRef to get the data from the blob

    docs.sdl.com/.../pub.xql

    This is the tricky part, and hard to explain. In my java code, it looks like this:

    int offsetInt = 0;
    int maxBytesInt = 200000;
    ByteArray myByteArray = new ByteArray(); // This is a special class I created to handle progressively expanding byte arrays
    while (offsetInt < size) { // The size is what you got in step 4 above
    if (offsetInt + maxBytesInt > size) {
    maxBytesInt = size - offsetInt;
    maxBytesInt++;
    }
    byte[] receivedBytes = getNextDataObjectChunkByIshLngRef(authid, lngRef, outputGUID, offsetInt, maxBytesInt); // lngRef is what you got in step 2, outputGUID is what you got in step 4
    myByteArray.add(receivedBytes, receivedBytes.length);
    offsetInt = offsetInt + receivedBytes.length;
    }

    That's pretty much it, and you can then do whatever you want with the byte stream.
    Note that sometimes the PDF byte streams can contain extra nulls that need to be trimmed off before saving out to a file.

Children