0

次のような xml 行セットが定義されています。

<root>
  <dataset1>
    <rows>
      <row id="0" title="Some Title" lookupValues="1;#Something1;#2;#Something2"/>
      <row id="1" title="Some other title" lookupValues="1;#Something1;#3;#Something3"/>
    </rows>
  </dataset1>
  <dataset2>
    <rows>
      <row id="1" lookupValue="Something1" anotherValue="ThisOne"/>
      <row id="2" lookupValue="Something2" anotherValue="ThatOne"/>
      <row id="3" lookupValue="Something3" anotherValue="TheOtherOne"/>
      <row id="4" lookupValue="Not Something"/>
    </rows>
  </dataset2>
</root>

そして、次のような形式に変換しようとしています:

<newroot>
  <rows>
    <row uniqueid="1" id="0" title="Some Title" lookupValue="Something1" anotherValue="ThisOne"/>
    <row uniqueid="2" id="0" title="Some Title" lookupValue="Something2" anotherValue="ThatOne"/>
    <row uniqueid="3" id="1" title="Some other title" lookupValue="Something1" anotherValue="ThisOne"/>
    <row uniqueid="4" id="1" title="Some other title" lookupValue="Something3" anotherValue="TheOtherOne"/>
  </rows>
</newroot>

重複する行に注意してください。これはアプリの要件です。また、欠落した lookupValue 行が削除されていることにも注意してください。

この変換を実現する本当に効率的な方法を知っている人はいますか?

ありがとう。

更新: 何を達成しようとしているのかをもっと明確にするべきでした。探しているマージのタイプをよりよく説明するために、いくつかの情報を追加しました。

更新 2:元のデータセットにエラーがあったことを除いて、与えられた答えはうまくいった可能性があります。つまり、lookupValues属性の形式です。ソース XML には実際のルックアップ テキストに加えてインデックス番号が含まれているため、区切り文字は少し異なります。

4

1 に答える 1

0

新しい行ごとに一意の id 値を生成することを除いて、これはすべて非常に簡単です。このためには、残念ながら、次の 2 つのパスを実行する必要があります。

XSLT1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exsl="http://exslt.org/common"
extension-element-prefixes="exsl">
<xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"/>

<xsl:key name="dataset2" match="row" use="@lookupValue" />

<xsl:variable name="new-rows">
    <xsl:for-each select="/root/dataset1/rows/row">
        <xsl:call-template name="generate-rows">
            <xsl:with-param name="values" select="@lookupValues"/>
        </xsl:call-template>
    </xsl:for-each>
</xsl:variable>

<xsl:template match="/">
    <newroot>
        <rows>
            <xsl:for-each select="exsl:node-set($new-rows)/row">
                <xsl:copy>
                    <xsl:attribute name="uniqueid">
                        <xsl:value-of select="position()"/>
                    </xsl:attribute>
                    <xsl:copy-of select="@*"/>
                </xsl:copy>
            </xsl:for-each>
        </rows>
    </newroot>
</xsl:template>

<xsl:template name="generate-rows">
    <xsl:param name="values"/>
    <xsl:param name="delimiter" select="';'"/>
    <xsl:variable name="token" select="substring-before(concat($values, $delimiter), $delimiter)" />
    <row id="{@id}" title="{@title}" lookupValue="{$token}" anotherValue="{key('dataset2', $token)/@anotherValue}"/>
    <xsl:if test="contains($values, $delimiter)">
        <!-- recursive call -->
        <xsl:call-template name="generate-rows">
            <xsl:with-param name="values" select="substring-after($values, $delimiter)"/>
        </xsl:call-template>
    </xsl:if>               
</xsl:template>

</xsl:stylesheet>

編集:

変更した入力を考慮して、generate-rowsテンプレートを次のように変更します。

<xsl:template name="generate-rows">
    <xsl:param name="values"/>
    <xsl:param name="delimiter" select="';#'"/>    
    <xsl:variable name="token" select="substring-before(substring-after(concat($values, $delimiter), $delimiter), $delimiter)" />
    <row id="{@id}" title="{@title}" lookupValue="{$token}" anotherValue="{key('dataset2', $token)/@anotherValue}"/>
    <xsl:if test="contains(substring-after($values, $delimiter), $delimiter)">
        <!-- recursive call -->
        <xsl:call-template name="generate-rows">
            <xsl:with-param name="values" select="substring-after(substring-after($values, $delimiter), $delimiter)"/>
        </xsl:call-template>
    </xsl:if>               
</xsl:template>
于 2014-12-29T18:55:09.540 に答える