简体   繁体   English

使用 SDL Tridion 2011 中的核心服务更新组件

[英]Updating Components using the Core Service in SDL Tridion 2011

I am updating a Component using Core Service in Tridion 2011.我正在使用 Tridion 2011 中的核心服务更新组件。

The sample code is as follows,示例代码如下,

string COMPONENT_URI = "tcm:8-674";
string SCHEMA_URI = "tcm:8-426-8";

ComponentData component = client.TryCheckOut(COMPONENT_URI, null) as ComponentData;

try
{
    Response.Write("<BR>" + component.Content);
    XDocument xdoc = XDocument.Parse(component.Content);
    var element = xdoc.Elements("first").Single();
    element.Value = "updated";
    xdoc.Save(component.Content);
    client.Save(component, null);
    Response.Write("<BR"+"SAVED");
}
catch (Exception ex)
{
    Response.Write("Unable to save comp" + ex.Message);
}

client.CheckIn(COMPONENT_URI, null);

I am getting following exception:我收到以下异常:

 Unable to save compSequence contains no elements 

Details:细节:

first - name of the field in the component first - 组件中字段的名称

Can any one help regarding this?任何人都可以帮助解决这个问题吗?

Thank you谢谢

The XML of a Component in Tridion is of the following format: Tridion中一个Component的XML格式如下:

<Content xmlns="uuid:2607D20D-1B22-4994-98C1-66D9ACF85C20">
  <first>The value of my first field</first>
  <second>The value of my second field</second>
</Content>

Your relevant code snippet is:您的相关代码片段是:

var element = xdoc.Elements("first").Single();

This is failing to select an element, since it is:这是 select 元素失败,因为它是:

  1. not providing a namespace to the selection不为选择提供名称空间
  2. only selecting direct children of the document root只选择文档根目录的直接子节点

You seem to expect that the default namespace will be automatically selected if you don't specify a namespace, which simply is not true.您似乎期望如果您不指定名称空间,系统会自动选择默认名称空间,但这根本不是真的。 As soon as you have XML that deals with namespaces, every query will have to specify the correct namespace.一旦您拥有处理命名空间的 XML,每个查询都必须指定正确的命名空间。

If you modify the code to deal with these two issues, it should look something like this:如果您修改代码来处理这两个问题,它应该看起来像这样:

XNamespace ns = xdoc.Root.GetDefaultNamespace();
var element = xdoc.Descendants(ns+"first").Single();

You might want to consider reading up on .NET handling of namespaces in XML and on XML namespaces in general, since this is a very common mistake that you simply need to get out of your system quickly.您可能需要考虑阅读 .NET handling of namespaces in XML 和 XML namespaces in general,因为这是一个非常常见的错误,您只需要快速离开您的系统。

People who have wanted to update the Component XML through the Core Service before you found the helper class given here useful.在您发现此处提供的帮助程序 class 有用之前,想要通过核心服务更新组件 XML 的人。

In addition as Mihai points out the way you invoke XDocument.Save is wrong.此外,正如 Mihai 指出的那样,您调用XDocument.Save的方式是错误的。 It expects a file name as its parameter, while you are passing it the XML of your Component.它需要一个文件名作为其参数,而您将组件的 XML 传递给它。

Your code attempts to save the XML DOM to a file.您的代码尝试将 XML DOM 保存到文件中。

XDocument.Save(string fileName) - Serialize this XDocument to a file, overwriting an existing file, if it exists. XDocument.Save(string fileName) - 将此XDocument序列化为文件,覆盖现有文件(如果存在)。

You should use something like this:你应该使用这样的东西:

using (var client = new SessionAwareCoreServiceClient(netTcpBinding, remoteAddress))
{
    ReadOptions readOptions = new ReadOptions();
    ComponentData component = client.Read(compTcmUri, readOptions) as ComponentData;
    XDocument dom = XDocument.Parse(component.Content);
    // do your modifications to dom
    component.Content = dom.ToString();
    component = client.Update(component, readOptions) as ComponentData;

    Console.WriteLine("Component updated: " + component.LocationInfo.WebDavUrl);
}

Sometimes, specially if you are synchronizing the content from a different repository that acts as the master, you can just reconstruct the component from scratch.有时,特别是如果您正在从充当主服务器的不同存储库同步内容,您可以从头开始重建组件。 In that case, here is a basic example of how to do that:在这种情况下,这里是如何做到这一点的基本示例:

    public static void updateComponent()
    {
        string componentWdUrl = "/webdav/020%20Content/Building%20Blocks/Content/wstest/testComponent.xml";
        CoreServicesUtil coreServicesUtil = new CoreServicesUtil();
        coreServicesUtil.coreServiceClient.CheckOut(componentWdUrl, true, coreServicesUtil.readOptions);
        ComponentData componentData = coreServicesUtil.getComponentData(componentWdUrl);
        SchemaData schemaData = coreServicesUtil.getSchemaData(componentData.Schema.IdRef);
        componentData.Content = xmlUtil.GetNewXmlNode("Content", schemaData.NamespaceUri);
        componentData.Metadata = xmlUtil.GetNewXmlNode("Metadata", schemaData.NamespaceUri);
        componentData.AddSingleField("singlefield", "singlefield sample", schemaData.NamespaceUri);
        componentData = (ComponentData)coreServicesUtil.coreServiceClient.Save(componentData, coreServicesUtil.readOptions);
        coreServicesUtil.coreServiceClient.CheckIn(componentData.Id, coreServicesUtil.readOptions);
        coreServicesUtil.coreServiceClient.Close();
    }

More description about methods used in this sample are explained in the article:有关此示例中使用的方法的更多说明,请参阅文章:

Faulted State error while creating component with Core Service 使用核心服务创建组件时出现错误 State

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM