1

I have a multi language site with the following structure:

siteroot
- en
-- home
-- login
-- etc.
- de
-- home
-- login
-- etc. 

The content beneath the language nodes is not necessarily the same. When switching languages I want to test if a parallel language node exists.

Currently I'm doing the following:

  • get current path
  • replace the language part of path e.g. replace /en/login to /de/login
  • the closest I've found to test the existence of a page is: XPathNodeIterator i = umbraco.library.GetXmlDocumentByUrl("http://localhost/de/login");

Debugging this shows, that umbraco actually hits the database. This can't be the best way to test the existence of a page.

Anybody have a better method at hand?

bowserm
  • 1,046
  • 10
  • 25
AyKarsi
  • 9,435
  • 10
  • 54
  • 92

2 Answers2

1

By the sounds your using the document class in cms.businesslogic.web namespace. This class is used for modifying/publishing nodes inside of umbraco.

Try using the node class that resides in umbraco.presentation.nodeFactory. This will interact with the in-memory XML cache only.

Node.GetCurrent() //static method - will give you the current loaded page.
Node.Parent //class property - will give parent method

The problem with the node class, that it can't take XPath queries (and will not give performance)

I've written a dynamic Linq provider that can be used to query the Umbraco XML structure using compiled xslt expressions. I going to be publishing in the next week or so. Let me know if your interested...

Elijah Glover
  • 1,968
  • 2
  • 14
  • 21
  • i used the business logic, exactly because it doesn't take xpath queries. your link provider sounds very interesting! – AyKarsi Oct 04 '10 at 07:02
  • Did you ever publish this?? I really want to get a node via path, as I have a control that needs data from some arbitrary path that have nothing to do with the current page. – jimplode Nov 30 '10 at 14:07
0

We have a multilingual site where we needed to do the same thing to set up our hreflang tags. There might be a better way, but I decided on building some Xpath to find out if a matching node exists in the other languages. We are using umbraco 7, and I would shy away from using NodeFactory if at all possible. It is depreciated. Using the umbraco helper won't hit the database, and is one of the best ways to query published content or media from umbraco for umbraco 7.

public static IPublishedContent GetLocalizedVersionOfPage(this IPublishedContent node, string regionName)
{
    var umbracoHelper = new UmbracoHelper(UmbracoContext.Current);
    var ancestorNames = node.AncestorsOrSelf()
                            .Where(n => n.Level > 1)
                            .OrderBy(n => n.Level)
                            .Select(n => n.Name).ToList();

    var xpath = new StringBuilder();
    xpath.AppendFormat("/root/HomePage[@nodeName='{0}']", regionName);
    foreach (var ancestorName in ancestorNames)
    {
        xpath.AppendFormat("/*[@nodeName='{0}']", ancestorName);
    }

    var matchingNode = umbracoHelper.TypedContentAtXPath(xpath.ToString()).FirstOrDefault();
    return matchingNode;
}

The above method is an extension method on the IPublishedContent. It allows you to pass in the region and it checks to see if a node with the same path determined by node name exists in the specified region. I thought about using the urlname instead of the node name. You could do that as well and maybe even make this faster by skipping the piece of code that does the .AncestorsOrSelf(). It just depends on how you want it to work. In my case, I wanted it to find a match based on the node name even if the url path was different, so I had to do the .AncestorsOrSelf(). Hope this helps.

Another thing to consider is how you call this method. if you use a loop like this:

@foreach (var region in Umbraco.TypedContentAtRoot().Where(n => n.IsDocumentType("HomePage")))
{
    var localizedVersion = currentPage.GetLocalizedVersionOfPage(region.Name);
    if (localizedVersion != null)
    {
        <link rel="alternate" href="@localizedVersion.UrlAbsolute()" hreflang="@LocalizeUtils.GetCulture(region.Name)" />
    }
}

You will end up getting the ancestors of the current node over and over once for each region because it calls .AncestorsOrSelf() every time you call GetLocalizedVersionOfPage(). It probably makes sense to refactor the GetLocalizedVersionOfPage method so you only have to call .AncestorsOrSelf once. If you do this sort of thing too many times, it starts to affect performance (especially if your site is very nested).

bowserm
  • 1,046
  • 10
  • 25