2013-09-21 5 views
-1

У меня нет большого опыта работы с XSLT. Мне нужна ваша помощь, чтобы подготовить правильное преобразование XSL для ниже xml. У меня есть XML, какВложенные для каждого в XSLT

<message> 
<requisition> 
    <data-values> 
     <data-value multi-valued="false"> 
      <name>Test_Grid-1.Name</name> 
      <value>1</value> 
     </data-value> 
     <data-value multi-valued="false"> 
      <name>Test_Grid-1.SupportType</name> 
      <value>Monthly,Quarterly</value> 
     </data-value> 
     <data-value multi-valued="false"> 
      <name>Test_Grid-1.Status</name> 
      <value>New</value> 
     </data-value> 
     <data-value multi-valued="false"> 
      <name>Test_Grid-2.Name</name> 
      <value>2</value> 
     </data-value> 
     <data-value multi-valued="false"> 
      <name>Test_Grid-2.SupportType</name> 
      <value>Monthly</value> 
     </data-value> 
     <data-value multi-valued="false"> 
      <name>Test_Grid-2.Status</name> 
      <value>Existing</value> 
     </data-value> 
    </data-values> 
</requisition> 
<agent-parameter multi-valued="false"> 
    <name>ActionType</name> 
    <value>New</value> 
</agent-parameter> 
<agent-parameter multi-valued="false"> 
    <name>Dictionary</name> 
    <value>Test_Grid</value> 
</agent-parameter> 
<agent-parameter multi-valued="false"> 
    <name>ActionName</name> 
    <value>SupportData</value> 
</agent-parameter> 
</message> 

Я хочу, чтобы подготовить XML, как это:

<ext:message> 
<ext:record> 
    <ext:name>SupportData</ext:name> 
    <ext:rowData> 
     <ext:rowAttribute name="Name">1</ext:rowAttribute> 
     <ext:rowAttribute name="SupportType">Monthly,Quarterly</ext:rowAttribute> 
     <ext:rowAttribute name="Status">New</ext:rowAttribute> 
    </ext:rowData> 
</ext:record> 
<ext:record> 
    <ext:name>SupportData</ext:name> 
    <ext:rowData> 
     <ext:rowAttribute name="Name">2</ext:rowAttribute> 
     <ext:rowAttribute name="SupportType">Monthly</ext:rowAttribute> 
     <ext:rowAttribute name="Status">Existing</ext:rowAttribute> 
    </ext:rowData> 
</ext:record> 

Можете ли вы помочь мне с Трансформации XSL для этого. Очень ценю вашу поддержку.

+0

Можно ли объяснить, как данные отображаются более подробно, просто чтобы убедиться, что все поняли проблему. Например, всегда будет три элемента на «запись» или может быть больше? Есть ли опечатка в вашем входном XML, кстати, поскольку второй элемент «name» имеет значение «1». Должно ли это соответствовать 2 вашим выводам? –

+0

Также вы используете XSLT 1.0 или XSLT 2.0 здесь? –

+0

Tim C, который исправляет второй элемент 'name', имеет значение '2'. Извините, опечатка. Каждая запись будет иметь имя и rowData. Элемент rowData будет иметь больше подэлементов, для простоты я дал только 3 элемента. Я использую XSLT 1.0. – Kiran

ответ

0

Это можно рассматривать как проблему группирования. У вас есть последовательные элементы, но вы хотите сгруппировать их с помощью элемента (или, точнее, части имя элемента перед полной остановкой, которая, как я полагаю, является логикой здесь). В XSLT 1.0 для этого обычно используется метод, называемый Muenchian Grouping.

Для начала определите ключ, который «группирует» значения данных по соответствующему имени.

<xsl:key name="record" match="data-value" use="substring-before(name, '.')" /> 

Таким образом, для данного имени, например, «Test_Grid-2», ключ будет содержать все элементы, необходимые в записи.

Чтобы начать вывод ваших записей, сначала нужно посмотреть на все данные-значения элементов, но выберите только те, которые появляются сначала в ключе для их заданного имени. Сравнение элементов осуществляется с помощью «генерировать-идентификатор()» метод, так что выражение выглядит следующим образом:

<xsl:apply-templates 
    select="requisition/data-values/data-value 
    [generate-id() = 
     generate-id(key('record', substring-before(name, '.'))[1])]" mode="record" /> 

(режим здесь, так как окончательный XSLT будет иметь два шаблона соответствие данных-значение так это будет различать их).

Затем в шаблоне, который соответствует отчетливое DATA-значение элементы, вы получите все элементы для вашей записи, как так

<xsl:apply-templates select="key('record', substring-before(name, '.'))" /> 

Одна вещь, чтобы отметить, ваш ожидается выход с помощью префикс пространства имен 'ext', но вы не указали объявление для префикса. (Возможно, потому, что вы просто упрощая пример), но я бы на самом деле ожидать выход начать так:

<ext:message xmlns:ext="http://mylovelynamespace.com"> 

Во всяком случае, попробовать это XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ext="ext"> 
    <xsl:output method="xml" indent="yes"/> 

    <xsl:key name="record" match="data-value" use="substring-before(name, '.')" /> 

    <xsl:template match="message"> 
     <ext:message> 
     <xsl:apply-templates select="requisition/data-values/data-value[generate-id() = generate-id(key('record', substring-before(name, '.'))[1])]" mode="record" /> 
     </ext:message> 
    </xsl:template> 

    <xsl:template match="data-value" mode="record"> 
     <ext:record> 
     <ext:name>SupportData</ext:name> 
     <xsl:apply-templates select="key('record', substring-before(name, '.'))" /> 
     </ext:record> 
    </xsl:template> 

    <xsl:template match="data-value"> 
     <ext:rowAttribute name="{substring-after(name, '.')}"><xsl:value-of select="value" /></ext:rowAttribute> 
    </xsl:template> 
</xsl:stylesheet> 

В XSLT 2.0, вы можете использовать xsl: for-each-group Конструкция упрощает группировку.

+0

Это работает идеально для моего требования. Большое спасибо. – Kiran

+0

Muenchian Grouping - очень полезный метод в XSLT 1.0, поэтому просто убедитесь, что вы все это прочитали! –

+0

во время работы с моим фактическим xml я ударил с другим сценарием, как показано ниже. Фактический ввод xml содержит разные значения данных (кроме Test_Grid-1 или Test_Grid-2 и т. Д.). В этом случае xsl вытягивает все эти элементы и показывает внутри ''. Есть ли способ, которым я могу установить переменную и присвоить значение как «Test_Grid-», и xsl вытащит только те значения данных, где начинается имя - с «Test_Grid-». – Kiran

0

Что-то вроде

<xsl:for-each select="data-value[position() mod 3 = 1]"> 
<ext:Record> 
    <ext:name>...</ext:name> 
    <ext:rowData> 
    <ext:rowAttribute name="Name"><xsl:value-of select="substring(substring-after(name, 'Test-Grid_'), 1, 1)"/></ext:rowAttribute> 
    <ext:rowAttribute name="SupportType"><xsl:value-of select="following-sibling[1]/value"/></ext:rowAttribute> 
    <ext:rowAttribute name="Status"><xsl:value-of select="following-sibling[2]/value"/></ext:rowAttribute> 
    </ext:rowData> 
</ext:Record> 
</xsl:for-each> 
+0

Майкл, спасибо за образец кода. Я не хочу жестко кодировать литерал «Test-Grid_», так как этот xml может иметь другое значение на основе входящего запроса. Есть ли способ сделать это достаточно умным, чтобы понять, что из xml? – Kiran

+0

Если вы можете указать правила, то, конечно, они могут быть закодированы. Но он не может быть достаточно интеллектуальным, чтобы угадать спецификацию (и я тоже не могу). –

Смежные вопросы