R.NET invoke function does not work - c#

I have all the necessary requirements when using the R.NET from http://rdotnet.codeplex.com/
My code works just fine on R Studio, however no luck on GUI. Can anybody let me know what I am doing wrong please?
REngine.SetEnvironmentVariables(#"C:\Program Files\R\R-3.1.1\bin\i386", #"C:\Program Files\R\R-3.1.1");
engine = REngine.GetInstance();
engine.Evaluate(#"source('C:/Users/achugh/Documents/Graphs/characterization.r')");
engine.Evaluate(#"source('C:/Users/achugh/Documents/Graphs/sliderDataToComputer.r')");
var sliderfunc = engine.Evaluate("sliderdata_yprofile").AsFunction();
var directory = engine.CreateCharacterVector(new[] { "C:/Users/achugh/Documents/Graphs/data" });
var oldset = sliderfunc.Invoke(new SymbolicExpression[] { directory }).AsDataFrame();
But for some reason the 'oldset' always evaluates to NULL. I already tried testing this via R-Studio
please advice?

Are you absolutely sure your function returns a data frame and not a matrix? The following behaves exactly as expected, and as you describe. I am working from the latest code but this part of R.NET is identical to the latest 1.5.16. Please mark this post as an answer if indeed correct, just not to confuse readers as to the behavior of R data coercion.
var funcDef = #"function(lyrics) {return(data.frame(a=1:4, b=5:8))}";
var f = engine.Evaluate(funcDef).AsFunction();
var x = f.Invoke(engine.CreateCharacter("Wo willst du hin?"));
Assert.True(x.IsDataFrame());
Assert.True(x.IsList());
var df = x.AsDataFrame();
Assert.NotNull(df);
funcDef = #"function() {return(as.matrix(data.frame(a=1:4, b=5:8)))}";
f = engine.Evaluate(funcDef).AsFunction();
x = f.Invoke();
Assert.False(x.IsDataFrame());
Assert.False(x.IsList());
df = x.AsDataFrame();
Assert.Null(df);
var nm = x.AsNumericMatrix();
Assert.NotNull(nm);

Answer:
var oldset = sliderfunc.Invoke(new SymbolicExpression[] { directory }).AsDataFrame();
change the above line to :
var oldset = sliderfunc.Invoke(new SymbolicExpression[] { directory }).AsNumericMatrix();
The reason are unknown, although the script is returning a data frame , but it fails to recognize this as data frame but recognizes this as Numeric Matrix.

Related

LibreOffice Calc C# SDK: program to insert images into cells, stuck trying to create XGraphic

Background: I'm trying to write a program to insert an image into a cell of a spreadsheet. LibreOffice recently changed how this is done, and all the samples I could find use the old method which no longer works.
Technically I know that you can't "insert" an image into a cell and that such an image is an overlay on a DrawPage that sits on top of the spreadsheet to "decorate" it.
One of the first steps in doing this (the new way) is to create an XGraphic object which contains the image. The process is to create an XGraphicProvider and call it with MediaProperties that specify the image file URL to be loaded. I have a program that is supposed to do this but the resulting XGraphic is null. The LO SDK gives pretty much no information when you do something wrong; it just doesn't work.
Here is the code I have, with all the headers removed:
// addpic
// add picture to spreadsheet - debug version
class OpenOfficeApp {
[STAThread]
static void Main(string[] args) {
bool lreadonly;
string pqfile;
string pqURL;
string pqpic;
pqfile = "file:///D:/Documents/NSexeye/ODS%20File%20Access/"+
"addpix/addpic.ods";
pqpic = "addpic2";
pqURL = pqpic+".jpg";
lreadonly = false;
Console.WriteLine("Using: "+pqfile);
// get the desktop
XComponentContext XCC = uno.util.Bootstrap.bootstrap();
XMultiComponentFactory XMCF =
(XMultiComponentFactory)XCC.getServiceManager();
XMultiServiceFactory XMSF = (XMultiServiceFactory)XCC.getServiceManager();
XComponentLoader XCL =
(XComponentLoader)XMSF.createInstance("com.sun.star.frame.Desktop");
// open the spreadsheet
PropertyValue[] pPV = new PropertyValue[2];
pPV[0] = new PropertyValue();
pPV[0].Name = "Hidden";
pPV[0].Value = new uno.Any(true);
pPV[1] = new PropertyValue();
pPV[1].Name = "ReadOnly";
if (lreadonly) pPV[1].Value = new uno.Any(true);
else pPV[1].Value = new uno.Any(false);
XComponent XCo = XCL.loadComponentFromURL(pqfile,"_blank",0,pPV);
// create graphic object containing image
object oGP = XMCF.createInstanceWithContext(
"com.sun.star.graphic.GraphicProvider",XCC);
if (oGP == null) {
Console.WriteLine("oGP is null. Aborting.");
return;
}
XGraphicProvider XGP = (XGraphicProvider)oGP;
if (XGP == null) {
Console.WriteLine("XGP is null. Aborting.");
return;
}
pPV = new PropertyValue[1];
pPV[0] = new PropertyValue();
pPV[0].Name = "URL";
pPV[0].Value = new uno.Any(pqURL);
Console.WriteLine("Creating XGraphic containing "+pqURL);
XGraphic XG = XGP.queryGraphic(pPV);
// *** XG is null here
if (XG == null) {
Console.WriteLine("XG is null. Aborting.");
return;
}
// ... lots of stuff to be added here
// save and close the spreadsheet
XModifiable XM = (XModifiable)XCo;
XM.setModified(true);
XStorable XSt = (XStorable)XCo;
XSt.store();
XCloseable XCl = (XCloseable)XCo;
XCl.close(true);
// terminate LibreOffice
// *** I want this to not terminate it if something else is open
XDesktop XD = (XDesktop)XCL;
if (XD != null) XD.terminate();
}
}
I get a null for the XGraphic, in the place indicated in the comments. I don't know if the call to create it is failing, or if one of the earlier steps of the process are incorrect.
My goal here, in addition to getting my program working, is to create a sample program showing how to add an image to a Calc spreadsheet cell, and to manipulate such images. There are a fair number of people asking questions about this and none of the examples I've found will work. I think a good working sample will be of value.
I've spent a lot of time searching for information and code samples for this, with nothing that helps. I've tried to find ways to verify the validity of the XGraphicProvider interface with no luck. I've run out of things to try.
I'm hoping someone who knows about the LibreOffice SDK can take a look and maybe see what I'm doing wrong.
Update: I figured out what I was doing wrong: I was passing a bare filename in the "URL" property to XGraphicProvider. It has to be the same format (starting with "file:///") as the spreadsheet's file name specification.
Now I'm stuck with another property problem. The XGraphic has to be specified as a parameter to the GraphicObjectShape's Graphic property, but the setPropertyValue() function requires that it be a uno.Any type. I can't figure out how to specify an interface name like XGraphic as a uno.Any.
Here is the piece of code that won't compile, complaining that it can't convert an XGraphic to a uno.Any, in the first setPropertyValue call:
// set image XGraphic
XPropertySet XPS = (XPropertySet)XS;
XPS.setPropertyValue("Graphic",XG);
XPS.setPropertyValue("Name",new uno.Any(pqpic));
XG is an XGraphic type. Using "new uno.Any(XG)" doesn't work either, giving a similar compiler error.
After trying unsuccessfully for a few hours to get the latest LO SDK up and running, let me offer some untested ideas.
First of all, here is some working Basic code, no doubt similar to what you're translating from. The important line is oShape.Graphic = oProvider.queryGraphic(Props()).
oDoc = ThisComponent
oSheet = oDoc.CurrentController.ActiveSheet
pqURL = "file:///C:/Users/JimK/Desktop/addpic.jpg"
oProvider = createUnoService("com.sun.star.graphic.GraphicProvider")
oShape = oDoc.createInstance("com.sun.star.drawing.GraphicObjectShape")
Dim Props(0) as new com.sun.star.beans.PropertyValue
Props(0).Name= "URL"
Props(0).Value = pqURL
oShape.Graphic = oProvider.queryGraphic(Props())
oCell = oSheet.getCellByPosition(5,5)
oShape.Name = oCell.AbsoluteName + "##" + Props(0).Value
oShape.Anchor = oCell
oSheet.DrawPage.add(oShape)
'Resize
w = oShape.Graphic.Size.Width
h = oShape.Graphic.Size.Height
wcl = oCell.Size.Width
hcl = oCell.Size.Height
If w<>0 and h<>0 then
oCell.String=""
Dim Size as new com.sun.star.awt.Size
Size.Width = wcl
Size.Height = h*wcl/w
If Size.Height > hcl then
Size.Width = hcl*w/h
Size.Height = hcl
Endif
oShape.setSize(Size)
oShape.setPosition(oCell.Position)
erase oShape
Else
oShape.dispose()
Endif
Now, how to translate this to C#? It looks like you may need to explicitly specify the type. In the SDK example, there are calls like this.
xFieldProp.setPropertyValue(
"Orientation",
new uno.Any(
typeof (unoidl.com.sun.star.sheet.DataPilotFieldOrientation),
unoidl.com.sun.star.sheet.DataPilotFieldOrientation.DATA ) );
So in your case, something like this:
XPS.setPropertyValue(
"Graphic"
new uno.Any(
typeof(unoidl.com.sun.star.graphic.XGraphic),
XG));
Alternatively, follow the suggestion here: set GraphicURL, which should load the image and set Graphic for you.

How to serialize tensor input required by dnnclassifier (serving_input_reciever)

I want to be able to use the dnnclassifier (estimator) on top of IIS using tensorflowsharp. The model has previously been trained in python. I got so far that I can now generate PB files, know the correct input/outputs, however I am stuck in tensorflowsharp using string inputs.
I can create a valid .pb file of the iris dataset. It uses the following feate_spec:
{'SepalLength': FixedLenFeature(shape=(1,), dtype=tf.float32, default_value=None), 'SepalWidth': FixedLenFeature(shape=(1,), dtype=tf.float32, default_value=None), 'PetalLength': FixedLenFeature(shape=(1,), dtype=tf.float32, default_value=None), 'PetalWidth': FixedLenFeature(shape=(1,), dtype=tf.float32, default_value=None)}
I have created a simple c# console to try and spin it up. The input should be an "input_example_tensor" and the output is located in "dnn/head/predictions/probabilities". This I discoved after alex_zu provided help using the saved_model_cli command here.
As far as I am aware all tensorflow estimator API's work like this.
Here comes the problem: the input_example_tensor should be of a string format which will be parsed internally by the ParseExample function. Now i am stuck. I have found TFTensor.CreateString, but this doesn't solve the problem.
using System;
using TensorFlow;
namespace repository
{
class Program
{
static void Main(string[] args)
{
using (TFGraph tfGraph = new TFGraph()){
using (var tmpSess = new TFSession(tfGraph)){
using (var tfSessionOptions = new TFSessionOptions()){
using (var metaGraphUnused = new TFBuffer()){
//generating a new session based on the pb folder location with the tag serve
TFSession tfSession = tmpSess.FromSavedModel(
tfSessionOptions,
null,
#"path/to/model/pb",
new[] { "serve" },
tfGraph,
metaGraphUnused
);
//generating a new runner, which will fetch the tensorflow results later
var runner = tfSession.GetRunner();
//this is in the actual tensorflow documentation, how to implement this???
string fromTensorflowPythonExample = "{'SepalLength': [5.1, 5.9, 6.9],'SepalWidth': [3.3, 3.0, 3.1],'PetalLength': [1.7, 4.2, 5.4],'PetalWidth': [0.5, 1.5, 2.1],}";
//this is the problem, it's not working...
TFTensor rawInput = new TFTensor(new float[4]{5.1f,3.3f,1.7f,0.5f});
byte[] serializedTensor = System.Text.Encoding.ASCII.GetBytes(rawInput.ToString());
TFTensor inputTensor = TensorFlow.TFTensor.CreateString (serializedTensor);
runner.AddInput(tfGraph["input_example_tensor"][0], inputTensor);
runner.Fetch("dnn/head/predictions/probabilities", 0);
//start the run and get the results of the iris example
var output = runner.Run();
TFTensor result = output[0];
//printing response to the client
Console.WriteLine(result.ToString());
Console.ReadLine();
}
}
}
}
}
}
}
This example will give the following error:
An unhandled exception of type 'TensorFlow.TFException' occurred in TensorFlowSharp.dll: 'Expected serialized to be a vector, got shape: []
[[Node: ParseExample/ParseExample = ParseExample[Ndense=4, Nsparse=0, Tdense=[DT_FLOAT, DT_FLOAT, DT_FLOAT, DT_FLOAT], dense_shapes=[[1], [1], [1], [1]], sparse_types=[], _device="/job:localhost/replica:0/task:0/device:CPU:0"](_arg_input_example_tensor_0_0, ParseExample/ParseExample/names, ParseExample/ParseExample/dense_keys_0, ParseExample/ParseExample/dense_keys_1, ParseExample/ParseExample/dense_keys_2, ParseExample/ParseExample/dense_keys_3, ParseExample/Const, ParseExample/Const, ParseExample/Const, ParseExample/Const)]]'
How can I serialize tensors in such a way that I can use the pb file correctly?
I also posted the issue on github, here you can find the iris example python file, pb file and the console applications. In my opinion solving this creates a
neat solution for all tensorflow users having ancient production environments (like me).
The Expected serialized to be a vector, got shape: [] error can be fixed by using an overload of the TFTensor.CreateString function: Instead of directly taking a string, the model apparently expects a vector containing a single string:
TFTensor inputTensor = TFTensor.CreateString(new byte[][] { bytes }, new TFShape(1));
The input_example_tensor in your case now expects a serialized Example protobuf message (see also the docs and the example.proto file).
Using the protobuf compiler, I've generated a C# file containing the Example class. You can download it from here: https://pastebin.com/iLT8MUdR. Specifically, I used this online tool with CSharpProtoc and replaced the import "tensorflow/core/example/feature.proto"; line by the messages defined in that file.
Once you've added the file to your project, you'll need a package reference to Google.Protobuf. Then, you can pass serialized examples to the model like this:
Func<float, Tensorflow.Feature> makeFeature = (float x) => {
var floatList = new Tensorflow.FloatList();
floatList.Value.Add(x);
return new Tensorflow.Feature { FloatList = floatList };
};
var example = new Tensorflow.Example { Features = new Tensorflow.Features() };
example.Features.Feature.Add("SepalLength", makeFeature(5.1f));
example.Features.Feature.Add("SepalWidth", makeFeature(3.3f));
example.Features.Feature.Add("PetalLength", makeFeature(1.7f));
example.Features.Feature.Add("PetalWidth", makeFeature(0.5f));
TFTensor inputTensor = TFTensor.CreateString(
new [] { example.ToByteArray() }, new TFShape(1));
runner.AddInput(tfGraph["input_example_tensor"][0], inputTensor);
runner.Fetch("dnn/head/predictions/probabilities", 0);
//start the run and get the results of the iris example
var output = runner.Run();
TFTensor result = output[0];

Attach screenshot to Test Step Result (ITestStepResult) - VSTS

I am able to create a new Test Run and update each Test Step status and finally complete the Automated Test RUN. I have used C# library files to do all these to VSTS.
Also I am currently working on attaching screenshot to the Test Step result. I can see that screenshot getting attached to the Test Step under Run tab but the upload was not complete and not able to see the screenshot getting loaded.
Following is the code used to attach screenshot:
ITestAttachment attachment = stepResult.CreateAttachment(screenShotPath);
stepResult.Attachments.Add(attachment);
Also please find the screenshot attached to understand my problem much better.
Thanks for the help in advance
With this code below, it uploads the attachment to test step, when I check the test result, the image isn’t displayed correctly (the same as you), but after a minute, it displays correctly. So, you can check image whether displays correctly now.
int testpointid = 56;
var u = new Uri("https://XXX.visualstudio.com");
var c = new VssClientCredentials();
c.Storage = new VssClientCredentialStorage(storageKind: "VssApp", storageNamespace: "VisualStudio");
TfsTeamProjectCollection _tfs = new TfsTeamProjectCollection(u, c);
_tfs.EnsureAuthenticated();
ITestManagementService test_service = (ITestManagementService)_tfs.GetService(typeof(ITestManagementService));
ITestManagementTeamProject _testproject = test_service.GetTeamProject("{proejct}");
ITestPlan _plan = _testproject.TestPlans.Find(89);
ITestRun testRun = _plan.CreateTestRun(false);
testRun.Title = "apiTest2";
ITestPoint point = _plan.FindTestPoint(testpointid);
testRun.AddTestPoint(point, test_service.AuthorizedIdentity);
testRun.Save();
testRun.Refresh();
ITestCaseResultCollection results = testRun.QueryResults();
ITestIterationResult iterationResult;
foreach (ITestCaseResult result in results)
{
iterationResult = result.CreateIteration(1);
foreach (Microsoft.TeamFoundation.TestManagement.Client.ITestStep testStep in result.GetTestCase().Actions)
{
ITestStepResult stepResult = iterationResult.CreateStepResult(testStep.Id);
stepResult.Outcome = Microsoft.TeamFoundation.TestManagement.Client.TestOutcome.Passed; //you can assign different states here
Microsoft.TeamFoundation.TestManagement.Client.ITestAttachment attachment = stepResult.CreateAttachment(#"{image path}");
stepResult.Attachments.Add(attachment);
iterationResult.Actions.Add(stepResult);
}
iterationResult.Outcome = Microsoft.TeamFoundation.TestManagement.Client.TestOutcome.Passed;
result.Iterations.Add(iterationResult);
result.Outcome = Microsoft.TeamFoundation.TestManagement.Client.TestOutcome.Passed;
result.State = TestResultState.Completed;
result.Save(true);
}
testRun.State = Microsoft.TeamFoundation.TestManagement.Client.TestRunState.Completed;
results.Save(true);

Getting "mergable revisions" with SharpSvn

When setting up a merge, the TortoiseSvn client has a wonderful checkbox labeled "Hide non-mergable revisions". I'm looking to reproduce the list of revisions that shows up when it's enabled using SharpSvn.
The TortoiseSvn documentation explains this checkbox:
When merge tracking is used, the log dialog will show previously merged revisions, and revisions pre-dating the common ancestor point, i.e. before the branch was copied, as greyed out. The Hide non-mergeable revisions checkbox allows you to filter out these revisions completely so you see only the revisions which can be merged.
How can I reproduce this functionality in SharpSvn code? I need a list of SvnLogEventArgs (or similar) that are candidates for merging.
Current status: I've only gotten as far as pulling the logs for both branches. I can't figure out how to get the appropriate svn:mergeinfo attribute or what to do with it once I get it.
I kept plugging away, and following links, and here's what I ended up with:
using (var client = new SvnClient())
{
var release = SvnTarget.FromUri(new Uri(#"https://******/branches/Release"));
var trunk = SvnTarget.FromUri(new Uri(#"https://******/trunk"));
string trunkMergeinfo, releaseMergeinfo;
client.GetProperty(release, "svn:mergeinfo", out releaseMergeinfo);
client.GetProperty(trunk, "svn:mergeinfo", out trunkMergeinfo);
var relInfos = releaseMergeinfo.Split("\n");
var trunkInfos = trunkMergeinfo.Split("\n");
// This is here because I don't know what will happen once I merge something into trunk.
Debug.Assert(relInfos.Except(trunkInfos).Count() == 1,"Too many unknown merge paths");
var trunklist = relInfos.SingleOrDefault(i => i.StartsWith("/trunk:"));
var revisions = trunklist.Replace("/trunk:", "").Split(",").SelectMany(t =>
{
// If the log contains a range, break it out to it's specific revisions.
if (t.Contains("-"))
{
var match = Regex.Match(t, #"(\d+)-(\d+)");
var start = int.Parse(match.Groups[1].Value);
var end = int.Parse(match.Groups[2].Value);
return Enumerable.Range(start, end - start + 1).ToArray();
}
else
return new[] { int.Parse(t) };
}).Select(x => (long)x);
Collection<SvnLogEventArgs> baseRevs;
// Why can't this take "trunk" or a property thereof as an argument?
client.GetLog(new Uri(#"https://******/trunk"), new SvnLogArgs { Start = 1725, End = SvnRevisionType.Head }, out baseRevs);
baseRevs.Reverse().Where(r => !revisions.Contains(r.Revision) ).Select(x => x.LogMessage).Dump();
}
Hopefully, this helps someone else, although I'll note that it does not have a lot of the sanity checking that I'd put in production code - this is the quick-and-dirty version.
Try SvnClient.ListMergesEligible:
http://sharpsvn.qqn.nl/current/html/M_SharpSvn_SvnClient_ListMergesEligible_1.htm
Edit.
SharpSVN seems bugged for me, so I went for cmd.
Check this out:
private static void mergelhetőVerziókListája()
{
string revíziók = cmd("svn", "mergeinfo --show-revs eligible \".../branches/dev\" \".../trunk\"");
}
private static string cmd(string utasítás, string paraméter)
{
StringBuilder eredmény = new StringBuilder();
Process cmd = new Process()
{
StartInfo = new ProcessStartInfo
{
FileName = utasítás,
Arguments = paraméter,
UseShellExecute = false,
RedirectStandardOutput = true,
CreateNoWindow = true
}
};
cmd.Start();
while (!cmd.StandardOutput.EndOfStream)
{
string kimenet = cmd.StandardOutput.ReadLine();
eredmény.AppendLine(kimenet); //...
}
return eredmény.ToString();
}

Creating an Ektron Smart Form Definition via the API

I've been trying to create a smart form definition from another application. The app successfully creates the smart form, but I'm unable to get the FieldList, DisplayXSLT or Schema fields to populate.
This leaves me with a blank smart form definition (less that ideal).
Here's the code I have to perform the action. Any ideas?
// form is a simple POCO with values copied from an existing SmartForm Definition
var config = new SmartFormConfigurationData();
config.SmartformTitle = form.Name;
config.SmartformDescription = form.Description;
config.XmlSchema = form.Schema;
config.PackageDisplayXslt = form.Xslt;
config.FieldList = form.FieldList;
config.Type = EkEnumeration.XmlConfigType.Content;
var api = new SmartFormConfigurationManager(ApiAccessMode.Admin);
api.RequestInformation.ServicesPath = this.EktronServiceHost;
api.RequestInformation.AuthenticationToken = this.GetAdminAuthToken();
api.Add(config);
Update:
I heard back from Ektron Support on this issue. It's not so much a "bug" per-se... It's more a case of this API class looking very similar to the ContentManager but not behaving like it. I expected that since it looked so similar to ContentManager and many of the other classes, I would be able to call Add() and it would just magically work. It turns out the solution is a little more complicated.
Adding a smartform is a two-step process: first Add(), then Update().
The Add method doesn't set all of the fields and in fact passes in NULL for a few of the parameters on the stored procedure that creates the entry in xml_collection_tbl.
The real fun comes in step 2. Basically, you start with the SmartForm's HTML -- the stuff you see when you're in the "Data Design" view for editing the smart form definition and you click that <> button ("HTML") at the bottom of the editor. You run that through a whole bunch of XSLTs that are burried in the WorkArea folder to construct the missing fields, and then you call update. Here's the code that worked for me:
var sfManager = new SmartFormConfigurationManager();
var data = sfManager.GetItem(12);
if (data == null) return;
var sfcData = new SmartFormConfigurationData();
sfcData.Type = EkEnumeration.XmlConfigType.Content;
sfcData.SmartformTitle = "SmartForm12 copy";
sfcData.SmartformDescription = "SmartForm12 copy";
sfcData.XmlSchema = "";
sfcData.PackageDisplayXslt = data.PackageDisplayXslt;
sfcData.FieldList = data.FieldList;
sfcData = sfManager.Add(sfcData);
Response.Write("SmartForm added with id: " + sfcData.Id);
var design = System.IO.File.ReadAllText(Server.MapPath("~/NewsArticleSmartForm.html"));
var contentApi = new ContentAPI();
var schema = contentApi.TransformXsltPackage(design, Server.MapPath("~/WorkArea/ContentDesigner/DesignToSchema.xslt"), true);
var fieldList = contentApi.TransformXsltPackage(design, Server.MapPath("~/WorkArea/ContentDesigner/DesignToFieldList.xslt"), true);
var viewEntryXslt = contentApi.TransformXsltPackage(design, Server.MapPath("~/WorkArea/ContentDesigner/DesignToEntryXSLT.xslt"), true);
var xsltArgs = new XsltArgumentList();
xsltArgs.AddParam("srcPath", "", "/WorkArea/ContentDesigner/");
var viewXsltSource = string.Concat("<root>", design, "<ektdesignpackage_list>", fieldList, "</ektdesignpackage_list></root>");
var viewXslt = contentApi.XSLTransform(viewXsltSource, Server.MapPath("~/WorkArea/ContentDesigner/DesignToViewXSLT.xslt"), true, false, xsltArgs, false);
var initialDocument = contentApi.TransformXsltPackage(design, Server.MapPath("~/WorkArea/ContentDesigner/PresentationToData.xslt"), true);
var sbPackage = new StringBuilder("<ektdesignpackage_forms><ektdesignpackage_form><ektdesignpackage_designs><ektdesignpackage_design>");
sbPackage.Append(design);
sbPackage.Append("</ektdesignpackage_design></ektdesignpackage_designs><ektdesignpackage_schemas><ektdesignpackage_schema>");
sbPackage.Append(schema);
sbPackage.Append("</ektdesignpackage_schema></ektdesignpackage_schemas><ektdesignpackage_lists><ektdesignpackage_list>");
sbPackage.Append(fieldList);
sbPackage.Append("</ektdesignpackage_list></ektdesignpackage_lists><ektdesignpackage_views><ektdesignpackage_view>");
sbPackage.Append(viewEntryXslt);
sbPackage.Append("</ektdesignpackage_view><ektdesignpackage_view>");
sbPackage.Append(viewXslt);
sbPackage.Append("</ektdesignpackage_view></ektdesignpackage_views><ektdesignpackage_initialDocuments><ektdesignpackage_initialDocument>");
sbPackage.Append(initialDocument);
sbPackage.Append("</ektdesignpackage_initialDocument></ektdesignpackage_initialDocuments></ektdesignpackage_form></ektdesignpackage_forms>");
sfcData.PackageXslt = sbPackage.ToString();
sfcData.FieldList = fieldList;
var baseFilename = "SmartForm" + sfcData.Id;
var schemaFilename = "/" + baseFilename + "Schema.xsd";
var xsltFilename = "/" + baseFilename + "Xslt.xslt";
sfcData.XmlSchema = schemaFilename; // The file will be prefixed with /XmlFiles
var unPackDisplayXslt = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><xsl:stylesheet version=\"1.0\" xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\"><xsl:output method=\"xml\" version=\"1.0\" encoding=\"UTF-8\" indent=\"yes\"/><xsl:template match=\"/\"><xsl:choose><xsl:when test=\"ektdesignpackage_forms/ektdesignpackage_form[1]/ektdesignpackage_views/ektdesignpackage_view[2]\"><xsl:copy-of select=\"ektdesignpackage_forms/ektdesignpackage_form[1]/ektdesignpackage_views/ektdesignpackage_view[2]/node()\"/></xsl:when><xsl:otherwise><xsl:copy-of select=\"ektdesignpackage_forms/ektdesignpackage_form[1]/ektdesignpackage_views/ektdesignpackage_view[1]/node()\"/></xsl:otherwise></xsl:choose></xsl:template></xsl:stylesheet>";
var displayXslt = contentApi.TransformXsltPackage(sbPackage.ToString(), unPackDisplayXslt, false);
System.IO.File.WriteAllText(Server.MapPath("~/XmlFiles" + xsltFilename), displayXslt);
sfcData.Xslt1 = xsltFilename; // The file will be prefixed with /XmlFiles
sfcData.DefaultXslt = 1;
sfManager.Update(sfcData);
I extracted the HTML for my existing smart form and saved in the root of my site as NewsArticleSmartForm.html. Here's what my file looked like:
<p>Author: <input type="text" name="Author" id="Author" ektdesignns_caption="Author" ektdesignns_name="Author" title="Author" ektdesignns_indexed="false" ektdesignns_nodetype="element" size="24" class="design_textfield" /></p>
<p> </p>
<p>Article Summary: <textarea name="Summary" id="Summary" ektdesignns_caption="Summary" ektdesignns_name="Summary" title="Summary" ektdesignns_indexed="false" ektdesignns_nodetype="element" cols="40" rows="3" class="design_textfield"></textarea>
</p>
<p> </p>
<p>Article Body:</p>
<p> </p>
<ektdesignns_richarea id="Body" name="Body" ektdesignns_caption="Body" ektdesignns_name="Body" title="Body" ektdesignns_indexed="false" ektdesignns_nodetype="element"> </ektdesignns_richarea>
<p> </p>
Good luck!
Original Answer:
Creating a copy of a SmartForm configuration should be fairly straight-forward. The SmartFormConfigurationData object has a Clone() method on it which makes it really easy to create a copy of an existing SmartForm. I say "should be" because it doesn't work.
I had an answer all typed out ready to post; I tried some code and it appeared to work. The new smartform was listed in the workarea, but when I clicked on that new smartform to view its details, I realized something was wrong.
I tried the following code:
var sfManager = new SmartFormConfigurationManager();
var config = sfManager.GetItem(7);
if (config == null) return;
var newSmartForm = config.Clone();
newSmartForm.SmartformTitle += " copy";
sfManager.Add(newSmartForm);
Here are the details from the original smartform:
And here's what the new smartform looked like -- the one I created with the frameworkAPI:
I did find one API method that successfully created a copy of an existing smartform:
var sfApi = new Ektron.Cms.ContentAPI();
var newId = sfApi.ReplicateXmlConfiguration(7, "copied sf title");
The problem with that method is that the smartform must exist on your system and you can only change the title. So, I went digging into the database to see what was happening. It turns out that after calling this ReplicateXmlConfiguration() method, the two database records are identical (except for the expected LastUpdated type of fields).
After calling the frameworkAPI's Update() method (same holds true when calling Add()), the "updated" record is clearly different.
I think we've got a genuine bug here. This happens both in v8.7 sp2 and v9.0 sp1. I've opened a case with Ektron support, and I'll update my answer as I hear back. They have always been very responsive when I've dealt with them in the past.

Categories

Resources