Прочитайте идентификаторы TCM многозначного встроенного поля, используя сценарий .NET Core Service


5

Я пытаюсь прочитать идентификатор TCM из многозначного встроенного поля с использованием Core Service. Я предпочел бы избегать использования XML и строковых манипуляций в максимально возможной степени и думал, что это выполнимо с использованием класса Fields, который я видел ранее (https://github.com/NunoLinhares/TridionWebData/blob/master/ImportContentFromRss/ImportContentFromRss/Content/Fields.cs)

Моя основная схема (Item Container) имеет многозначное поле под названием «items» ", который принимает внедренную схему. Вложенная схема имеет 2 поля: accountUrl (который берет строку) и значок (который является ComponentLinkField). Я хочу найти все компоненты, используя Item Container, а затем в цикле получить идентификатор TCM связанного компонента «icon». Затем я прочитаю компонент из этого TCM и проверьте, какая схема используется. Проблема в том, что когда я запускаю свой цикл, он получит только первое появление «элементов» и получит поле «значок» TCM, но затем цикл выйдет, и он захватит следующий компонент, даже если есть несколько «элементов» "в первом контейнере предметов.

// TCM ID of the main schema who's field we want to check 
// Ex tcm: 8-44-8 is Item Container 
string mainComponentSchemaTcm = "tcm:8-44-8"; 

// XML name of the schema field we want to check 
string checkComponentField = "icon"; 

// Schema of the linked component we want to know if it is used in checkComponentField 
string linkedComponentSchema = "Image"; 

// Are we checking embedded fields? 
bool checkEmbeddedFields = true; 

// If we are checking embedded fields what is the parent field/attribute holding the embedded field(s) 
string parentField = "items"; 

// Creating the core service. 
// Using "wsHttp_2013" binding to create the client, Other bindings (like "netTcp_2013") could be used depending on the need. 
SessionAwareCoreServiceClient client = new SessionAwareCoreServiceClient("wsHttp_2013"); 

// Set up our search query filter to look only for components 
SearchQueryData filter = new SearchQueryData(); 
filter.ItemTypes = new ItemType[] { ItemType.Component }; 

// In our case we only want components using a specific schema so we use it's TCM ID 
// We use BasedOnSchemaData to get all the schema information and then set the filter above 
// to use this specific schema 
BasedOnSchemaData mainSchema = new BasedOnSchemaData(); 
mainSchema.Schema = new LinkToSchemaData() { IdRef = mainComponentSchemaTcm }; 
filter.BasedOnSchemas = new BasedOnSchemaData[] { mainSchema }; 

// Get the schema fields of our main schema using mainComponentSchemaTcm. 
// Ex tcm: 8-44-8 is Item Container which contains the field "items" 
// we also need to set whether we are checking and expanding embedded fields. 
// For our Item Container "items" uses embedded fields "AccountURL" and "icon" 
SchemaFieldsData schemaFields = client.ReadSchemaFields(mainComponentSchemaTcm, checkEmbeddedFields, new ReadOptions()); 

// Get list of components using our filter 
var componentSearchResults = client.GetSearchResults(filter); 

// We want to check each component in our results 
foreach (var component in componentSearchResults) 
{ 
    var currentItem = (ComponentData)component; 

    // currentItem does not contain complete data for current component so we need to read the full data with client.Read 
    ComponentData compReadData = (ComponentData)client.Read(currentItem.Id, new ReadOptions()); 

    // get content of component/schema fields for current component 
    var fieldsContent = Fields.ForContentOf(schemaFields, compReadData); 
    string tcmOfIcon = ""; 

    foreach (var field in fieldsContent) 
    { 
     if (!string.IsNullOrEmpty(field.Value)) 
     { 
      tcmOfIcon = field[checkComponentField].Value; 
     } 
    } 
} 

Этот код является неполным, но основной проблемой является Еогеасп (вар поле в fieldsContent) будет выполнять только один раз на каждый компонент. Возможно ли это сделать так, как я пытаюсь или это единственный способ проанализировать XML?

Спасибо, что посмотрели!

5

Ключевым моментом здесь является то, что, в то время как для обычных полей, то значение (или значения) свойство даст вам значение поля, но для встроенных полей схемы вы должны использовать свойство SubFields. Это даст вам один или несколько объектов поля, содержащих поля внутри встроенной схемы.

Ваш код станет что-то вроде этого (он мог бы использовать некоторые дополнительные нуль-проверку, но я пропустил, что для ясности)

foreach (var component in componentSearchResults) 
{ 
    var currentItem = (ComponentData)component; 

    // currentItem does not contain complete data for current component so we need to read the full data with client.Read 
    ComponentData compReadData = (ComponentData)client.Read(currentItem.Id, new ReadOptions()); 

    // get content of component/schema fields for current component 
    var fieldsContent = Fields.ForContentOf(schemaFields, compReadData); 
    string tcmOfIcon = ""; 

    foreach (var embeddedField in fieldsContent["name_of_embedded_field"].SubFields) 
    { 
     tcmOfIcon = embeddedField["name_of_icon_field"].Value; 
     //do something with this tcm uri and move on to the next 
    } 
} 

1

Я думаю, его легче получить XML-узлов и отслеживать содержание ...

foreach (XElement element in client.GetListXml(currentItem.Id, yourFilterData).Nodes()) 
       { 
        var itemXML = element.ToString(); //to inspect the content 
        var itemTitle = element.Attribute("Title").Value; 
        var itemType = element.Attribute("Type").Value.ToString(); 
        var itemID = element.Attribute("ID").Value.ToString(); 
        ...     

       } 
+1

Это может быть более легким метод в целом, но я специально хотел сделать это без просто разбора строк или XML. Я не очень много работал с Core Service, и, изучая его, я хочу узнать больше о том, что он может сделать и к чему я имею доступ. Спасибо за ваш ответ, хотя это должно делать то, что мне нужно. 25 янв. 172017-01-25 15:59:35