2017-02-01 4 views
1

Использование SaxonHE 9.7/XPath-2,0XSLT-2,0: Объединяя результаты текущей группе() в одну

Мой XML:

<osm> 
    <node> 
    <tag k="fhrs:id" v="204258"/> 
    <tag k="name" v="King of Wessex"/> 
    </node> 
    <node> 
    <tag k="fhrs:id" v="139245"/> 
    <tag k="name" v="The Royal Oak"/> 
    </node> 
    <node> 
    <tag k="fhrs:id" v="204258"/> 
    <tag k="name" v="The Rising Sun"/> 
    </node> 
    etc... 
</osm> 

Я возвращаю все дублированные значения (v=) от fhrs:id используя:

Я преобразовываю выход в формат geojson. Это требует, чтобы каждый элемент, кроме конечного, заканчивался запятой. В других подпрограммах я использовал это, чтобы проверить, если он является последним:

<xsl:template match="/*/*/tag"> 
    { 

    ...<snip>... 

    }<xsl:if test="position() &lt; last()">,</xsl:if> 
</xsl:template> 

Однако, поскольку в этом случае xsl:apply-templates только проходя два за один раз, каждый элемент отсутствует запятую на выходе GeoJSON ,

Есть ли способ объединить все выходы xsl:for-each-group в один, прежде чем передать его xsl:apply-templates или альтернативный способ найти конечный элемент? Есть ли xsl:for-each-group даже лучший способ сделать это?

Я рассмотрел различные способы использования переменных/массивов, но не соответствует размеру счета.

ответ

2

Вы можете изменить

<xsl:template match="/">  
    <xsl:for-each-group select="/*/*/tag[@k='fhrs:id']" group-by="@v"> 
     <xsl:apply-templates select="current-group() [current-group()[2]]"/> 
    </xsl:for-each-group> 
</xsl:template> 

в

<xsl:template match="/"> 
    <xsl:variable name="duplicates" as="element()*">  
    <xsl:for-each-group select="/*/*/tag[@k='fhrs:id']" group-by="@v"> 
     <xsl:sequence select="current-group() [current-group()[2]]"/> 
    </xsl:for-each-group> 
    </xsl:variable> 
    <xsl:apply-templates select="$duplicates"/> 
</xsl:template> 

Что касается проблемы с last(), Saxonica воспроизвел эту проблему сообщили в https://saxonica.plan.io/issues/3122, я думаю, в вашем случае вы можете избежать использования last() с помощью несколько отличная проверка position() gt 1, но до вывода содержимого:

<xsl:template match="/*/*/tag"> 
    <xsl:if test="position() gt 1">,</xsl:if> 
    { 

    "value" : "<xsl:value-of select="@v"/>" 

    } 
</xsl:template> 

<xsl:template match="/"> 
    <xsl:variable name="duplicates" as="element()*">  
     <xsl:for-each-group select="/*/*/tag[@k='fhrs:id']" group-by="@v"> 
      <xsl:sequence select="current-group() [current-group()[2]]"/> 
     </xsl:for-each-group> 
    </xsl:variable> 
    <xsl:apply-templates select="$duplicates"/> 
</xsl:template> 

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

+0

Я пробовал это ранее и Saxon возвращает «Последовательность более чем одного элемента не допускается как значение переменной $ duplicates (, , ...)« – DaveF

+0

@DaveF, извините, что тип 'element() *' для последовательности. –

+0

Это сработало, за исключением last() возвращало общее количество ** всех ** fhrs: id значений не только дублированных. Поэтому я передал переменную 'duplicates' в прикладной шаблон: ' \t \t \t \t \t ' и использовать его так: '} , 'Является в лучшем wqay ? – DaveF

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