5

Is there a way to ignore the root element when using GetListXml? Take a look at the below code, I check what objData is and then loop over each result, however I need to ignore the root element ONLY when Settings.TridionPublicationOrStructureGroupId is a publicationId.

    using (var client = new CoreServiceClient("basicHttp"))
    {
        var objData = (IdentifiableObjectData)client.Read(
                 Settings.TridionPublicationOrStructureGroupId, new ReadOptions());
        XElement sgXml = null;

        if (objData is PublicationData)
        {
            sgXml = client.GetListXml(Settings.TridionPublicationOrStructureGroupId, 
                new RepositoryItemsFilterData
                {
                    ItemTypes = new[] { ItemType.StructureGroup },
                    Recursive = true
                });

            //Ignore the root element??
        }
        else if(objData is StructureGroupData)
        {
            sgXml = client.GetListXml(Settings.TridionPublicationOrStructureGroupId,
                        new OrganizationalItemItemsFilterData
                        {
                            ItemTypes = new[] { ItemType.StructureGroup },
                            Recursive = true
                        });
        }

        if (sgXml != null)
        {
            Log.DebugFormat("Found {0} sg(s)", sgXml.DescendantsAndSelf().Count());

            foreach (var sg in sgXml.DescendantsAndSelf()))
            {
               Console.WriteLine(sg.Attribute("ID").Value);
            }
        }
    }

Is this possible?

4
  • 1
    As stated, this is a .NET question, but I sense there is an underlying Tridion question. What are you trying to achieve, and why did you write the code like this? Commented May 5, 2013 at 20:34
  • Hi Dominic, thanks for your comment. I just wanted to give the user the option to enter either a publication Id or sg Id to loop over sgs. I am writing a script that copies sgs from one publication to another and at the moment the command line argument just takes the publication Id and then loop over each sg. When I come to test this I don't want to do this everytime so I want to be able to target specific sgs too - if that makes sense :-) Commented May 6, 2013 at 9:42
  • The question's title seems very out of context with the actual question - do you mind re-writing the title?
    – Nuno Linhares
    Commented May 6, 2013 at 21:01
  • If you only want to go one level deep, you can get the children with .Elements(). For a deep copy, you probably want to code it recursively anyway. Commented May 6, 2013 at 22:32

4 Answers 4

3

How about:

using (var client = new CoreServiceClient("basicHttp"))
{
    var objData = (IdentifiableObjectData)client.Read(
                 Settings.TridionPublicationOrStructureGroupId, new ReadOptions());
    XElement sgXml = null;
    IEnumerable<XElement> elements = null;

    if (objData is PublicationData)
    {
       sgXml = client.GetListXml(Settings.TridionPublicationOrStructureGroupId, 
                new RepositoryItemsFilterData
                {
                    ItemTypes = new[] { ItemType.StructureGroup },
                    Recursive = true
                });

       elements = sgXml.Descendants();
    }
    else if(objData is StructureGroupData)
    {
         sgXml = client.GetListXml(Settings.TridionPublicationOrStructureGroupId,
                 new OrganizationalItemItemsFilterData
                 {
                     ItemTypes = new[] { ItemType.StructureGroup },
                     Recursive = true
                 });

       elements = sgXml.DescendantsAndSelf();
    }

    //defensive check
    if(elements!= null && elements.Any())
    {
      //Process elements
      Log.DebugFormat("Found {0} sg(s)", elements.Count());

      foreach (var element in elements))
      {
         Console.WriteLine(element.Attribute("ID").Value);
      }
    }
}
0
4

Rather than using sgXml.DescendantsAndSelf(), just use sgXml.Descendants()

1
  • Hi Siva, I can't use Descendants(). I need to get the root element only if the tcm id provided isn't that of a publication id. This is because I'm trying to use the StructureGroupData class and my code will fail when it tried to read a publication. Commented May 6, 2013 at 19:02
2

In order for XML to be valid, there has to be a root element. Its up to you to ignore the root element or not. For the GetListXml method in your cases, the root element contains the ID of the items that you are searching within.

<tcm:ListItems ID="tcm:x-xxx-x" Managed="512" xmlns:tcm="http://www.tridion.com/ContentManager/5.0">
    <tcmItem ID="tcm:12-123-4" Title="some title" Type="4" ........ />
    ...
</tcm:ListItems>

Siva was correct that you can use Descendants(), but it sounds like you are doing an inclusive search when the ID passed is a SG, so your code is using the ID attribute of the root element to read as a StructureGroupData, which of course is failing when its a Publication because this ID will then be the ID of the Publication you searched within. You can easily just adjust your code though.

The first thing, you don't have to open up the item to check whether or not its a Publication or StructureGroup, the tcm uri contains everything you need. If that last section of the ID is "-1", its a Publication. If its a "-4", its a StructureGroup. Based off this, you can easily make a bool IsStructureGroup(string id) method.

You also really don't need that root element... if it is a StructureGroup, you already have that ID because its what you passed in. If you are hard set on using it however, you can do something like:

IEnumerable<XElement> items = IsStructureGroup(Settings.TridionPublicationOrStructureGroupId) ? sgXml.DescendantsAndSelf() : sgXml.Descendants();

foreach (var sg in items)
{
    Console.WriteLine(sg.Attribute("ID").Value);
}

You can even use Descendants() on both Publications or StructureGroups, and just ignore any element with an ID attribute that contains a Publication. There are many options and different routes that you can do to achieve what you wish.

3
  • Hi Alex, thanks for your suggestion. I did try using your approach but got a null exception. This is because I need to use a different filter when using publication or sg. If you look at the code from Chris below you'll see what I mean. Commented May 7, 2013 at 8:06
  • Yes, different filters are needed, you already had that piece of the code working, I was just giving you the end piece. :)
    – Alex Klock
    Commented May 7, 2013 at 10:52
  • Thanks Alex. It's working a treat now. Trying to find a way to speed it up now as the script is taking AGES to run completely. Commented May 7, 2013 at 12:16
1

I tend to use something like this in my foreach loops:

foreach(XElement node in client.GetListXml("tcm:1045-3733-2", filter).Nodes())
{
    Console.WriteLine("Found item " + node.Attribute("ID").Value);
}

This loops through all child nodes of the result of the GetListXml method.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.