How can I get the 'key' of a keyword from an XSLT TBB?

孤街浪徒 提交于 2019-12-05 21:51:41

It seems it's impossible to get an xlink:href to the referred keyword in a Keyword field using just the XSLT Mediator.

To overcome this I created a .NET compound that "inflates" the extra keyword info in the XML. You'll have to place this compound just before the XSLT compound.

Code:

namespace ContentManagement.TBB.Templates
{
   [TcmTemplateTitle("Inflate Keyword Info")]
    public class GetExtendedComponent : TemplateBase
    {
       public override void Transform(Engine engine, Package package)
       {
           Initialize(engine, package);

           Component component = GetComponent();
           XmlElement componentXml = component.ToXml();

           XmlNamespaceManager ns = new XmlNamespaceManager(componentXml.OwnerDocument.NameTable);
           ns.AddNamespace("ns", component.Schema.NamespaceUri);

           ItemFields fields = new ItemFields(component.Content, component.Schema);
           InflateKeywords(fields, (XmlElement)componentXml.SelectSingleNode(String.Format("//ns:{0}", component.Schema.RootElementName), ns));

           ItemFields metaFields = new ItemFields(component.Metadata, component.MetadataSchema);
           InflateKeywords(metaFields, (XmlElement)componentXml.SelectSingleNode("//ns:Metadata", ns));

           Item xmlItem = package.CreateStringItem(ContentType.Component, componentXml.OuterXml);
           package.Remove(package.GetByName(Package.ComponentName));
           package.PushItem(Package.ComponentName, xmlItem);
       }

       private void InflateKeywords(ItemFields fields, XmlElement element)
       {
           XmlNamespaceManager ns = new XmlNamespaceManager(element.OwnerDocument.NameTable);
           ns.AddNamespace("ns", element.NamespaceURI);
           Logger.Debug("NS: " + element.NamespaceURI);
           foreach (ItemField field in fields)
           {
               if (field is KeywordField)
               {
                   KeywordField keywordField = (KeywordField)field;

                   XmlNodeList nodes = element.SelectNodes(String.Format("./ns:{0}", keywordField.Name), ns);
                   foreach (XmlNode node in nodes)
                   {
                       XmlElement kwelement = (XmlElement)node;

                       Logger.Debug(String.Format("Keyword titel: {0}", keywordField.Value.Title));
                       Logger.Debug(String.Format("Keyword Element Value: {0}", kwelement.InnerText));

                       kwelement.SetAttribute("href", "http://www.w3.org/1999/xlink", keywordField.Values.First(v => v.Title.Equals(kwelement.InnerText)).Id);
                       kwelement.SetAttribute("type", "http://www.w3.org/1999/xlink", "simple");
                       kwelement.SetAttribute("title", "http://www.w3.org/1999/xlink", kwelement.InnerText);
                   }
               }
               else if (field is EmbeddedSchemaField)
               {
                   EmbeddedSchemaField embedField = (EmbeddedSchemaField)field;

                   XmlNodeList nodes = element.SelectNodes(String.Format("./ns:{0}", embedField.Name), ns);
                   int i = 0; 
                   foreach (XmlNode node in nodes)
                   {
                       XmlElement embedElement = (XmlElement)node;
                       InflateKeywords(embedField.Values[i], embedElement);
                       i++;
                   }
               }

           }
       }
    }
}

The Key of the Keyword is not stored in the link (which really only contains the minimal information needed to look up the Keyword). So you'll have to load the Keyword and read it from there.

Yoav showed how to read other items from within your XSLT here:

http://yoavniran.wordpress.com/2009/07/11/implementing-the-xslt-mediator-part-1/

This snippet seems relevant:

<xsl:attribute name="alt">
    <xsl:value-of select="document(simple:image/@xlink:href)/tcm:Component/tcm:Data/tcm:Metadata/image:Metadata/image:altText"/>
</xsl:attribute>

So the document() call loads the linked item (in this case a multimedia component) and the rest of the select then finds the value they are looking for.

A keyword XML looks like this:

<?xml version="1.0"?>
<tcm:Keyword xmlns:transform-ext="urn:tridion:transform-ext" 
    xmlns:i="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:xlink="http://www.w3.org/1999/xlink" 
    xmlns:tcm="http://www.tridion.com/ContentManager/5.0" 
    IsEditable="false" ID="tcm:1-233-1024">
    <tcm:Context>
        <tcm:Publication xlink:title="000 Parent Publication" xlink:href="tcm:0-1-1" 
            xlink:type="simple"/>
        <tcm:OrganizationalItem xlink:title="Places" xlink:href="tcm:1-37-512" 
            xlink:type="simple"/>
    </tcm:Context>
    <tcm:Info>
        <tcm:LocationInfo>
            <tcm:WebDAVURL>/webdav/000%20Parent%20Publication/Places/New%20Keyword.tkw</tcm:WebDAVURL>
            <tcm:Path>\000 Parent Publication\Places</tcm:Path>
        </tcm:LocationInfo>
        <tcm:BluePrintInfo>
            <tcm:OwningPublication xlink:title="000 Parent Publication" xlink:href="tcm:0-1-1" xlink:type="simple"/>
            <tcm:IsShared>false</tcm:IsShared>
            <tcm:IsLocalized>false</tcm:IsLocalized>
        </tcm:BluePrintInfo>
        <tcm:VersionInfo>
            <tcm:CreationDate>2012-06-11T09:09:03</tcm:CreationDate>
            <tcm:RevisionDate>2012-06-11T09:09:03</tcm:RevisionDate>
            <tcm:Creator xlink:title="TCMHOSTNAME\Administrator" 
                xlink:href="tcm:0-11-65552" xlink:type="simple"/>
        </tcm:VersionInfo>
        <tcm:AllowedActions>
            <tcm:Actions Managed="0" Deny="96" Allow="268560384"/>
        </tcm:AllowedActions>
    </tcm:Info>
    <tcm:Data>
        <tcm:Title>New Keyword</tcm:Title>
        <tcm:Description>New Keyword</tcm:Description>
        <tcm:Key>Key</tcm:Key>
        <tcm:IsAbstract>false</tcm:IsAbstract>
        <tcm:ParentKeywords/>
        <tcm:RelatedKeywords/>
        <tcm:MetadataSchema xlink:title="" xlink:href="tcm:0-0-0" xlink:type="simple"/>
        <tcm:Metadata/>
        <tcm:IsRoot>true</tcm:IsRoot>
    </tcm:Data>
</tcm:Keyword>

Implement this way:-

To get the Value field:-

document(simple:keywordlink/@xlink:href)/tcm:Keyword/tcm:Data/tcm:Title/text()

<xsl:value-of select="document(simple:keywordlink/@xlink:href)/tcm:Keyword/tcm:Data/tcm:Title/text()" />

Result:

Some Value

To get the Key field:-

document(simple:keywordlink/@xlink:href)/tcm:Keyword/tcm:Data/tcm:Key/text()

<xsl:value-of select="document(simple:keywordlink/@xlink:href)/tcm:Keyword/tcm:Data/tcm:Key/text()" />

Result:

Its ID is 123
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!