Объединение пар узлов на основе атрибута, нового для сопоставления с шаблоном - PullRequest
2 голосов
/ 04 мая 2011

Скажем, у меня есть следующий XML:

<root>
   <tokens>
      <token ID="t1">blah</token>
      <token ID="t2">blabla</token>
      <token ID="t3">shovel</token>
   </tokens>

   <relatedStuff>
      <group gID="s1">
        <references tokID="t1"/>
        <references tokID="t2"/>
      </group>

      <group gID="s2">
        <references tokID="t3"/>
      </group>

   </relatedStuff>
</root>

Теперь, учитывая, что цикл для каждого для каждого токена был бы довольно неэффективным и плохая идея , как бы поступитьоб использовании сопоставления с шаблоном для преобразования этого xml в следующее?

<s id="everything_merged"> 
    <tok id="t1" gID="s1" >blah</tok> 
    <tok id="t2" gID="s1" >blabla</tok> 

    <tok id="t3" gID="s2" >shovel</tok>
</s> 

Все, что я хочу от <s>, это "gID", gID, соответствующий токену в <tokens>.

<xsl:for-each select="b:root/a:tokens/a:token">
    <!-- and here some template matching -->
    <xsl:attribute name="gID">
         <xsl:value-of select="--correspondingNode's--@gID"/>
    </xsl:attribute>

</xsl:for-each>

Я довольно размышляю над подобными вещами, поэтому большое спасибо за любую помощь!

Ответы [ 2 ]

2 голосов
/ 04 мая 2011

Следующая таблица стилей:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="/">
        <s id="everything_merged">
            <xsl:apply-templates select="/root/tokens/token" />
        </s>
    </xsl:template>
    <xsl:template match="token">
        <tok id="{@ID}" gID="{/root/relatedStuff/group[
                                references[@tokID=current()/@ID]]/@gID}">
            <xsl:apply-templates />
        </tok>
    </xsl:template>
</xsl:stylesheet>

Применяется к этому входу (с поправкой на правильность формы):

<root>
    <tokens>
        <token ID="t1">blah</token>
        <token ID="t2">blabla</token>
        <token ID="t3">shovel</token>
    </tokens>
    <relatedStuff>
        <group gID="s1">
            <references tokID="t1" />
            <references tokID="t2" />
        </group>
        <group gID="s2">
            <references tokID="t3" />
        </group>
    </relatedStuff>
</root>

Производит:

<s id="everything_merged">
    <tok id="t1" gID="s1">blah</tok>
    <tok id="t2" gID="s1">blabla</tok>
    <tok id="t3" gID="s2">shovel</tok>
</s>
1 голос
/ 05 мая 2011

Решение с использованием ключей и чистого «push-style» :

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:key name="kgIDfromTokId" match="@gID"
  use="../*/@tokID"/>

 <xsl:template match="tokens">
  <s id="everything_merged">
   <xsl:apply-templates/>
  </s>
 </xsl:template>

 <xsl:template match="token">
  <tok id="{@ID}" gID="{key('kgIDfromTokId', @ID)}">
   <xsl:apply-templates/>
  </tok>
 </xsl:template>
</xsl:stylesheet>

при применении к предоставленному документу XML :

<root>
    <tokens>
        <token ID="t1">blah</token>
        <token ID="t2">blabla</token>
        <token ID="t3">shovel</token>
    </tokens>
    <relatedStuff>
        <group gID="s1">
            <references tokID="t1" />
            <references tokID="t2" />
        </group>
        <group gID="s2">
            <references tokID="t3" />
        </group>
    </relatedStuff>
</root>

желаемый, правильный результат получается :

<s id="everything_merged">
   <tok id="t1" gID="s1">blah</tok>
   <tok id="t2" gID="s1">blabla</tok>
   <tok id="t3" gID="s2">shovel</tok>
</s>
...