2009-08-14 6 views
5

Я вытягиваю то, что осталось от моих волос, пытаясь получить простой внешний интерфейс, работающий с использованием Saxon 9.1.0.7.XSLT 2.0 Внешний поиск с использованием ключа() и документа()

У меня есть простой исходный файл dummy.xml:

<something> 
    <monkey> 
     <genrecode>AAA</genrecode> 
    </monkey> 
    <monkey> 
     <genrecode>BBB</genrecode> 
    </monkey> 
    <monkey> 
     <genrecode>ZZZ</genrecode> 
    </monkey> 
    <monkey> 
     <genrecode>ZER</genrecode> 
    </monkey> 
</something> 

Затем файл перекодировки GenreSet_124.xml:

<GetGenreMappingObjectsResponse> 
    <tuple> 
     <old> 
     <GenreMapping DepartmentCode="AAA" 
         DepartmentName="AND - NEWS AND CURRENT AFFAIRS" 
         Genre="10 - NEWS"/> 
     </old> 
    </tuple> 
    <tuple> 
     <old> 
     <GenreMapping DepartmentCode="BBB" 
         DepartmentName="AND - NEWS AND CURRENT AFFAIRS" 
         Genre="11 - NEWS"/> 
     </old> 
    </tuple> 

    ... lots more 
</GetGenreMappingObjectsResponse> 

Что я m, пытающийся достичь, - это просто получить «Жанр «значение, основанное на значении« DepartmentCode ».

Так что мой XSL выглядит следующим образом:

... 
<!-- Set up the genre lookup key --> 
<xsl:key name="genre-lookup" match="GenreMapping" use="@DepartmentCode"/> 


<xsl:variable name="lookupDoc" select="document('GenreSet_124.xml')"/> 

<xsl:template match="/something"> 
<stuff> 
    <xsl:for-each select="monkey"> 
     <Genre> 

     <xsl:apply-templates select="$lookupDoc"> 
     <xsl:with-param name="curr-label" select="genrecode"/> 
     </xsl:apply-templates> 

     </Genre> 
    </xsl:for-each> 
</stuff> 
</xsl:template> 

<xsl:template match="GetGenreMappingObjectsResponse"> 
    <xsl:param name="curr-genrecode"/> 

    <xsl:value-of select="key('genre-lookup', $curr-genrecode)/@Genre"/> 

</xsl:template> 

...


Проблема, что у меня есть, что я ничего не получаю обратно. В настоящее время я просто получить

<?xml version="1.0" encoding="UTF-8"?> 
<stuff> 
    <Genre/> 
    <Genre/> 
    <Genre/> 
    <Genre/> 
</stuff> 

Я переместил все данные подстановок быть атрибутами GenreMapping, ранее в качестве дочерних элементов GenreMapping всякий раз, когда я вошел в матч шаблон = «GetGenreMappingObjectsResponse» это просто напечатать бы из всего текста из любого GenreMapping (DepartmentCode, DepartmentName, Жанр)!

Я не могу для жизни меня выяснить, что я делаю неправильно. Любая помощь или предложения были бы весьма признательны.

Вы можете найти текущую фактическую XSLT листинг:.

<?xml version="1.0"?> 
<xsl:stylesheet version="2.0" 
       xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
       xmlns:xs="http://www.w3.org/2001/XMLSchema"> 

<!-- Define the global parameters --> 
<xsl:param name="TransformationID"/> 
<xsl:param name="TransformationType"/> 

<!-- Specify that XML is the desired output type --> 
<xsl:output method="xml" encoding="UTF-8" indent="yes"/> 

<!-- Set up the genre matching capability --> 
<xsl:key name="genre-lookup" match="GenreMapping" use="@DepartmentCode"/> 

<xsl:variable name="documentPath"><xsl:value-of select="concat('GenreSet_',$TransformationID,'.xml')"/></xsl:variable> 
<xsl:variable name="lookupDoc" select="document($documentPath)"/> 

<!-- Start the first match on the Root level --> 
<xsl:template match="/something"> 
<stuff> 
    <xsl:for-each select="monkey"> 
     <Genre> 
     <xsl:apply-templates select="$lookupDoc/*"> 
     <xsl:with-param name="curr-genrecode" select="string(genrecode)"/> 
     </xsl:apply-templates> 
     </Genre> 
    </xsl:for-each> 
</stuff> 
</xsl:template > 

<xsl:template match="GetGenreMappingObjectsResponse"> 
    <xsl:param name="curr-genrecode"/> 
    <xsl:value-of select="key('genre-lookup', $curr-genrecode, $lookupDoc)/@Genre"/> 
</xsl:template> 
</xsl:stylesheet> 

TransformationID является все дни 124 (так открыт правильный файл поиска Тип это просто имя, что я в настоящее время не используется, но намереваясь

.
+0

Какой XSLT-компилятор вы используете? – Welbog

+0

Saxon-B 9.1.0.7 – 2009-08-14 15:18:29

+0

Цифры. Я не знаком с этим. Может быть, позже Томалак придет и поможет вам. Работает ли ключ без ключа? – Welbog

ответ

7

в XSLT 2.0 есть два способа, которые вы можете сделать то, что вы хотите:

Одна версии трехпараметрической функций key Третий параметр позволяет указать корневой узел вы хотите ключ работать на (. по умолчанию это всегда корень основного документа):

<xsl:value-of select="key('genre-lookup', $curr-genrecode,$lookupDoc)/@Genre"/> 

Другой способ заключается в использовании функции key под $lookupDoc узла:

<xsl:value-of select="$lookupDoc/key('genre-lookup', $curr-genrecode)/@Genre"/> 

Оба эти метода описаны в XSLT 2.0 specification on keys, и не будет работа в XSLT 1.0.

Для полноты вам придется переписать это, чтобы не использовать ключи, если вы ограничены XSLT 1.0.

<xsl:value-of select="$lookupDoc//GenreMapping[@DepartmentCode = $curr-genrecode]/@Genre"/> 

Aha! Проблема заключается в том, что select="$lookupDoc" в вашем вызове apply-templates вызывает шаблон по умолчанию, а не тот, который вы ожидаете, поэтому параметр теряется.

Изменить его к этому:

<xsl:apply-templates select="$lookupDoc/*"> 
    <xsl:with-param name="curr-genrecode" select="string(genrecode)"/> 
</xsl:apply-templates> 

Это будет вызывать шаблон правильно и ключ должен работать.

Таким образом, окончательный XSLT лист должен выглядеть следующим образом:

<xsl:variable name="lookupDoc" select="document('XMLFile2.xml')"/> 
    <xsl:key name="genre-lookup" match="GenreMapping" use="@DepartmentCode"/> 
    <xsl:template match="/something"> 
    <stuff> 
     <xsl:for-each select="monkey"> 
     <Genre> 
      <xsl:apply-templates select="$lookupDoc/*"> 
      <xsl:with-param name="curr-genrecode" select="string(genrecode)"/> 
      </xsl:apply-templates> 
     </Genre> 
     </xsl:for-each> 
    </stuff> 
    </xsl:template> 
    <xsl:template match="GetGenreMappingObjectsResponse"> 
    <xsl:param name="curr-genrecode"/> 
    <xsl:value-of select="key('genre-lookup',$curr-genrecode,$lookupDoc)/@Genre"/> 
    </xsl:template> 

(Source of information)

+0

HI там, Спасибо за ответ. Я уже пробовал (и теперь повторил) оба из них (изнутри шаблона мастера, я не называю apply-template, используя эту форму), и оба возвращают ничего. Я все еще получаю пустые элементы ?! Возможно, что-то, что я делаю неправильно в настройке ключа? Отношения – 2009-08-14 13:57:55

+0

Это может быть проблема с вашим компилятором XSLT, но использование '$ lookupDoc/*' должно охватывать ваши базы. – Welbog

+0

Здравствуйте, снова, Используя обновленный код, я больше не получаю пустые элементы. Я получаю их заполненными пробелами (24 строки). Я сейчас действительно озадачен. – 2009-08-14 14:43:02

0

ОК, так что это немного умственная, и я не претендую, чтобы понять это, но это работает (звучит как карьера в программном обеспечении).

Проблема, с которой я столкнулся, заключается в том, что когда я вызываю шаблоны-заявки и передаю внешний документ в качестве переменной, он никогда не сопоставлял шаблоны, даже те, которые назывались «Genremapping».

Поэтому я использовал подстановочный знак, чтобы поймать его, также при вызове шаблонов-примаков я сузил узел, который был дочерним, которого я интересовал. Это было довольно странно, я мог распечатать имя узла и см. «GenreMapping», но он никогда не попадал ни в один шаблон, который я назвал «GenreMapping», вместо этого выбирал только шаблон «*».

Это означает, что мой новый шаблонный шаблон вызывается для каждого отдельного узла GenreMapping, поэтому он может быть немного неэффективным. То, что я понял тогда, было всем, что мне нужно было сделать, это распечатать, если предикат совпадет.

Так это выглядит, как это сейчас (без ключа используется вообще):

... 
<xsl:template match="/something"> 
<stuff> 
    <xsl:for-each select="monkey"> 
     <Genre> 
     <key_value><xsl:value-of select="genrecode"/></key_value> 
     <xsl:variable name="key_val"><xsl:value-of select="genrecode"/></xsl:variable> 
     <code> 
     <xsl:apply-templates select="$lookupDoc/*/*/*/*"> 
     <xsl:with-param name="curr-genrecode" select="string(genrecode)"/> 
     </xsl:apply-templates> 

     </code> 
     </Genre> 
    </xsl:for-each> 
</stuff> 
</xsl:template > 


<xsl:template match="*"> 
    <xsl:param name="curr-genrecode"/> 
    <xsl:value-of select=".[@DepartmentCode = $curr-genrecode]/@Genre"/> 
</xsl:template> 
... 

Все это выход: Примечание, последняя key_value правильно не имеет ввода кода, поскольку нет никакого состязания в поисковый документ.

<?xml version="1.0" encoding="UTF-8"?> 
<stuff xmlns:xs="http://www.w3.org/2001/XMLSchema"> 
    <Genre> 
     <key_value>AAA</key_value> 
     <code>10 - NEWS</code> 
    </Genre> 
    <Genre> 
     <key_value>AAA</key_value> 
     <code>10 - NEWS</code> 
    </Genre> 
    <Genre> 
     <key_value>BBB</key_value> 
     <code>11 - NEWS</code> 
    </Genre> 
    <Genre> 
     <key_value>SVVS</key_value> 
     <code/> 
    </Genre> 
</stuff> 

Ответьте на почтовый индекс. Спасибо за помощь Welbog.

+0

Я рад, что вы нашли рабочее решение, хотя это странно. – Welbog