2014-11-07 3 views
0

Недавно я начал работать над XSLT. У меня есть требование группировать значения узлов на основе поля id. Однако поле id может быть дублирующимся. Например, скажем ниже, это структура XML.Как объединить общие значения id в XSLT

<ProductResults> \t 
 
<ProductResult> \t      
 
\t \t <ProductId>1000</ProductId> 
 
\t \t <Location>Bangalore</Location> 
 
\t \t <ModuleNumber>02</ModuleNumber> 
 
       <StoreId>1234<StoreId> \t \t \t \t 
 
</ProductResult> 
 
<ProductResult> \t  \t 
 
\t \t <ProductId>2000</ProductId> 
 
\t \t <ModuleNumber>03</ModuleNumber> 
 
\t \t <Location>Bangalore</Location> 
 
       <StoreId>1234<StoreId> \t 
 
</ProductResult> 
 
<ProductResult> \t 
 
\t \t <ProductId>1000</ProductId> 
 
\t \t <ModuleNumber>01</ModuleNumber> 
 
\t \t <Location>Mumbai</Location> 
 
       <StoreId>1234<StoreId> \t 
 
</ProductResult> 
 
<ProductResult> \t \t 
 
\t \t <ProductId>4000</ProductId> 
 
\t \t <ModuleNumber>02</ModuleNumber> 
 
\t \t <Location>Kolkata</Location> 
 
       <StoreId>1234<StoreId> \t 
 
</ProductResult> 
 
<ProductResult> \t \t 
 
\t \t <ProductId>1000</ProductId> 
 
\t \t <ModuleNumber>03</ModuleNumber> 
 
\t \t <Location>Chennai</Location> 
 
       <StoreId>1234<StoreId> \t 
 
</ProductResult> 
 
</ProductResults>

Если вы заметили, то PRODUCTID 1000 повторяется трижды. Я должен написать XSLT для производства ниже результата.

{ 
 
    "StoreId": "1234", 
 
    "Locations": [ 
 
    { 
 
     "ProductId": "1000", 
 
     "Locations": [ 
 
     { 
 
      "Location": "Bangalore", 
 
      "ModuleNumber": "02" 
 
     }, 
 
     { 
 
      "Location": "Mumbai", 
 
      "ModuleNumber": "01" 
 
     }, 
 
     { 
 
      "Location": "Chennai", 
 
      "ModuleNumber": "03" 
 
     } 
 
     ] 
 
    }, 
 
    { 
 
     "ProductId": "2000", 
 
     "Locations": [ 
 
     { 
 
      "Location": "Bangalore", 
 
      "ModuleNumber": "03" 
 
     } 
 
     ] 
 
    }, 
 
    { 
 
     "ProductId": "4000", 
 
     "Locations": [ 
 
     { 
 
      "Location": "Kolkata", 
 
      "ModuleNumber": "02" 
 
     } 
 
     ] 
 
    } 
 
    ] 
 
}

Поскольку поле ProductID повторяется, я не могу использовать цикл Еогеасп непосредственно, который создает дополнительный блок кода для той же ProductID. Любые предложения по этому вопросу ?.

Заранее спасибо.

+0

Это * группировка * вопрос - выполните поиск. Обратите внимание, что для XSLT 1.0 или 2.0 разные ответы. –

ответ

0

Следующая XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output method="xml" omit-xml-declaration="yes" 
      version="1.0" encoding="UTF-8" indent="yes"/> 
<xsl:strip-space elements="*"/> 
<xsl:template match="@*|node()"> 
    <xsl:apply-templates select="@*|node()" /> 
</xsl:template> 
<xsl:template match="@*|node()"> 
<xsl:variable name="uniqueProducts" 
       select="count(//ProductId[not(. = following::ProductId)])"/> 
{ 
"StoreId": <xsl:value-of select="ProductResult/StoreId"/>, 
"Locations": [ 
<xsl:for-each select="//ProductId[not(. = following::ProductId)]"> 
    <xsl:sort select="."/> 
    { 
    "ProductId": "<xsl:value-of select="."/>, 
    "Locations": [ 
    <xsl:call-template name="location"> 
     <xsl:with-param name="productId" select="."/> 
    </xsl:call-template> 
    ] 
    <xsl:if test="position() &lt; $uniqueProducts">,</xsl:if> 
</xsl:for-each> 
]} 
</xsl:template> 
<xsl:template name="location"> 
<xsl:param name="productId"/> 
<xsl:for-each select="//ProductResult[ProductId=$productId]"> 
{ 
"Location": "<xsl:value-of select="Location"/>", 
"ModuleNumber": "<xsl:value-of select="ModuleNumber"/>" 
    } 
    <xsl:if test="position() != last()">,</xsl:if> 
</xsl:for-each> 
</xsl:template> 
</xsl:stylesheet> 

применительно к следующему (исправлено, так как вы не закрыли StoreId в вашем примере)
Входной XML:

<ProductResults>  
    <ProductResult>      
    <ProductId>1000</ProductId> 
    <Location>Bangalore</Location> 
    <ModuleNumber>02</ModuleNumber> 
    <StoreId>1234</StoreId>     
    </ProductResult> 
    <ProductResult>   
    <ProductId>2000</ProductId> 
    <ModuleNumber>03</ModuleNumber> 
    <Location>Bangalore</Location> 
    <StoreId>1234</StoreId>  
    </ProductResult> 
    <ProductResult> 
    <ProductId>1000</ProductId> 
    <ModuleNumber>01</ModuleNumber> 
    <Location>Mumbai</Location> 
    <StoreId>1234</StoreId>  
    </ProductResult> 
    <ProductResult>  
    <ProductId>4000</ProductId> 
    <ModuleNumber>02</ModuleNumber> 
    <Location>Kolkata</Location> 
    <StoreId>1234</StoreId>  
    </ProductResult> 
    <ProductResult>  
    <ProductId>1000</ProductId> 
    <ModuleNumber>03</ModuleNumber> 
    <Location>Chennai</Location> 
    <StoreId>1234</StoreId>  
    </ProductResult> 
</ProductResults> 

производит следующие
Выход XML:

{ 
"StoreId": 1234, 
"Locations": [ 

{ 
    "ProductId": "1000, 
    "Locations": [ 

{ 
"Location": "Bangalore", 
"ModuleNumber": "02" 
    } 
    , 
{ 
"Location": "Mumbai", 
"ModuleNumber": "01" 
    } 
    , 
{ 
"Location": "Chennai", 
"ModuleNumber": "03" 
    } 
    ] 
    , 
{ 
    "ProductId": "2000, 
    "Locations": [ 

{ 
"Location": "Bangalore", 
"ModuleNumber": "03" 
    } 
    ] 
    , 
{ 
    "ProductId": "4000, 
    "Locations": [ 

{ 
    "Location": "Kolkata", 
    "ModuleNumber": "02" 
    } 
    ] 
]} 

Обратите внимание, что это всего лишь пример для группировки, например. дополнительный цикл для каждого из них можно было бы отрегулировать, чтобы заботиться о более чем одном StoreId.
Для упрощения Я только что написал это для одного StoreId, предоставленного с использованием <xsl:value-of select="ProductResult/StoreId"/> вместо проверки на разные значения StoreId и обработки всех них.

Для получения подробной информации вы можете проверить эту статью Jeni Tennison http://www.jenitennison.com/xslt/grouping/muenchian.xml для Muenchian Grouping и вы можете, например. посмотрите на http://www.dpawson.co.uk/xsl/sect2/N4486.html для XSLT Grouping.

Update: Просто регулируются первым отправил XSLT, и для объяснения, как это работает - обработка контура в качестве <xsl:for-each select="//ProductId[not(. = following::ProductId)]"> всех уникальных ProductId значения, вызывая <xsl:template name="location"> с текущим ProductId в качестве параметра и генерирование выходного сигнала для каждого места, которое соответствует ProductId , Хотя обновленный подход не использует Muenchian Grouping, он все равно может быть полезен для вас, поэтому я сохраню ссылку.

+0

Привет матовый, большое спасибо за быстрый ответ. Я попытался применить вышеприведенную логику, но при загрузке XSLT-файла для преобразования я получаю сообщение об ошибке: «Имя не может начинаться с«. ». символ, шестнадцатеричное значение 0x2E '. Я провел некоторое исследование по этому вопросу. Мало кто говорит, что это проблема с кодировкой, но я пытался представить UTF-16 в XSLT-файле, но не работал для меня. Любые предложения по этому поводу? – user3796454

+0

@ user3796454 Я только что проверил проблему и думаю, что исправил ее - см. Обновленный XSLT в ответ.Хотя я скорректировал первую версию на текущий, я случайно скорректировал '' To ' 'который вызвал ошибку. Должен работать сейчас, сохранил демо здесь: http://xsltransform.net/3NzcBsU/4 –

+0

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

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