1

アプリケーション用に変換する必要がある XML データ (GraphML) があります。XML は、ラベル「User」および「Item」のノードと、ラベル「HAS_HOBBY」および「FRIEND_OF」のエッジを持つグラフを表します。

特定のユーザーを指定して、少なくとも 1 つの趣味を共有するすべての彼の友人と、それらの趣味 (アイテムで表される) を変換後に取得したいと考えています。「友達」は「FRIEND_OF」エッジ要素で、趣味は「HAS_HOBBY」で表されます。

必要なアイテムと友達を見つけることができるXSLT(これはちょっと新しい)がありますが、私の論理では、友達を1回だけコピーすることはできません-元のユーザーと共有する趣味ごとに1回行われます. これを行うには、ユーザーの趣味ごとに友人の趣味をそれぞれ調べます。一致した場合は、アイテム (趣味) (これで問題ありません) と友人を印刷しますが、この友人は試合のたびに印刷されます。が見つかり、この友人が複数回出現することになり、望ましくありません。

これを回避する方法を探してみましたが、このソリューションを実装するロジック全体に欠陥があると思います。とはいえ、他にアイデアはありません。

ここに私のXSLがあります:

<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:ns="http://graphml.graphdrawing.org/xmlns"
    xmlns="http://graphml.graphdrawing.org/xmlns"
    exclude-result-prefixes="ns #default">
  <xsl:strip-space elements="*"/>
  <xsl:output indent="yes"/>



  <!--Identity template: default copy all content into the output -->
  <xsl:template match="node()|@*">
    <xsl:copy>
      <xsl:apply-templates select="node()|@*"/>
    </xsl:copy>
  </xsl:template>

  <!-- Don't copy tags called 'node or edge' -->
  <xsl:template match="ns:node" />
  <xsl:template match="ns:edge" />



  <xsl:template match="ns:node[ns:data[@key='username' and . = 'c']]">
    <xsl:copy>
      <xsl:apply-templates select="node()|@*"/>
    </xsl:copy>

    <xsl:variable name="USERID" select="@id"/>

    <xsl:for-each select="//ns:edge"> 

      <xsl:if test="@source=$USERID">

        <xsl:variable name="TARGET" select="@target"/>
        <xsl:for-each select="//ns:node[@id=$TARGET]">
          <!-- finds USERNAME's hobbies -->

          <xsl:for-each select="//ns:edge[@source=$USERID and @label='HAS_HOBBY']">
            <xsl:variable name="HOBBYTARGET" select="@target"/>
            <xsl:for-each select="//ns:edge[@source=$TARGET and @label='HAS_HOBBY']">
              <xsl:if test="@target=$HOBBYTARGET">
                <!-- Shared hobby with friend -->
                <xsl:for-each select="//ns:node[@id=$HOBBYTARGET]">
                  <xsl:copy>
                    <xsl:apply-templates select="node()|@*"/>
                  </xsl:copy>
                </xsl:for-each>


              </xsl:if>
            </xsl:for-each>  
          </xsl:for-each>
        </xsl:for-each>
      </xsl:if>

      <xsl:if test="@target=$USERID">

        <xsl:variable name="SOURCE" select="@source"/>
        <xsl:for-each select="//ns:node[@id=$SOURCE]">
          <!-- finds USERNAME's hobbies -->

          <xsl:for-each select="//ns:edge[@source=$USERID and @label='HAS_HOBBY']">
            <xsl:variable name="HOBBYTARGET" select="@target"/>
            <xsl:for-each select="//ns:edge[@source=$SOURCE and @label='HAS_HOBBY']">
              <xsl:if test="@target=$HOBBYTARGET">
                <!-- Shared hobby with friend -->
                <xsl:for-each select="//ns:node[@id=$HOBBYTARGET]">
                  <xsl:copy>
                    <xsl:apply-templates select="node()|@*"/>
                  </xsl:copy>
                </xsl:for-each>


              </xsl:if>
            </xsl:for-each>  
          </xsl:for-each>

        </xsl:for-each>
      </xsl:if>
    </xsl:for-each>

  </xsl:template>

</xsl:stylesheet>

現時点では友人のコピーがありませんが、「友人との共通の趣味」コメントの直後になります。

「フラグ」タイプの変数を使用できないことに気付きました(不可能であるため..)。また、配列や同様のデータ構造を持つ方法がないため、本当にアイデアがありません。

少なくとも 1 つの趣味 (アイテム) を共有しているユーザーの友人と、その趣味自体を取得するのを手伝ってください。

EDIT:サンプル入力:見やすいようにグラフの視覚化も追加しました

ここに画像の説明を入力

<?xml version="1.0" encoding="UTF-8"?>
<graphml xmlns="http://graphml.graphdrawing.org/xmlns" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd">
<graph id="G" edgedefault="directed">

<node id="n2" labels=":Item"><data key="labels">:Item</data><data key="itemId">Q1</data></node>
<node id="n32" labels=":Item"><data key="labels">:Item</data><data key="itemId">Q8</data></node>
<node id="n51" labels=":Item"><data key="labels">:Item</data><data key="itemId">Q23</data></node>
<node id="n897" labels=":Item"><data key="labels">:Item</data><data key="itemId">Q55</data></node>

<node id="n406727" labels=":User"><data key="labels">:User</data><data key="hobbies">[Ljava.lang.String;@78ba00a3</data><data key="firstName">a</data><data key="imgPath">/uploads/a.png</data><data key="surName">a</data><data key="username">a</data><data key="gender">Male</data><data key="relaStatus">Single</data></node>
<node id="n406729" labels=":User"><data key="labels">:User</data><data key="hobbies"></data><data key="firstName">b</data><data key="imgPath">/uploads/b.png</data><data key="surName">b</data><data key="username">b</data><data key="gender">Male</data><data key="relaStatus">Single</data></node>
<node id="n406731" labels=":User"><data key="labels">:User</data><data key="hobbies"></data><data key="blocked">[Ljava.lang.String;@7b800b40</data><data key="firstName">c</data><data key="imgPath">/uploads/c.png</data><data key="surName">c</data><data key="username">c</data><data key="gender">Male</data><data key="relaStatus">Single</data></node>
<node id="n406734" labels=":User"><data key="labels">:User</data><data key="hobbies"></data><data key="firstName">d</data><data key="imgPath">/uploads/d.png</data><data key="surName">d</data><data key="username">d</data><data key="gender">Male</data><data key="relaStatus">Single</data></node>

<edge id="e1223400" source="n406727" target="n406729" label="FRIEND_OF"><data key="label">FRIEND_OF</data></edge>
<edge id="e1223403" source="n406727" target="n406731" label="FRIEND_OF"><data key="label">FRIEND_OF</data></edge>
<edge id="e1223405" source="n406734" target="n406731" label="FRIEND_OF"><data key="label">FRIEND_OF</data></edge>
<edge id="e1223405" source="n406727" target="n406734" label="FRIEND_OF"><data key="label">FRIEND_OF</data></edge>

<edge id="e1223374" source="n406727" target="n2" label="HAS_HOBBY"><data key="label">HAS_HOBBY</data></edge>
<edge id="e1223385" source="n406727" target="n51" label="HAS_HOBBY"><data key="label">HAS_HOBBY</data></edge>
<edge id="e1223383" source="n406729" target="n2" label="HAS_HOBBY"><data key="label">HAS_HOBBY</data></edge>
<edge id="e1223384" source="n406731" target="n2" label="HAS_HOBBY"><data key="label">HAS_HOBBY</data></edge>
<edge id="e1223375" source="n406731" target="n51" label="HAS_HOBBY"><data key="label">HAS_HOBBY</data></edge>
<edge id="e1223371" source="n406734" target="n897" label="HAS_HOBBY"><data key="label">HAS_HOBBY</data></edge>

</graph>
</graphml>

そして、これがサンプル出力です。cとbだけがaと共通の趣味(Qのついたもの)を持っているので、結果に残っていることがわかります。そのため、d、エッジ広告と Q51、Q8 がなくなりました。

ここに画像の説明を入力

<?xml version="1.0" encoding="UTF-8"?>
<graphml xmlns="http://graphml.graphdrawing.org/xmlns" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd">
<graph id="G" edgedefault="directed">

<node id="n2" labels=":Item"><data key="labels">:Item</data><data key="itemId">Q1</data></node>
<node id="n51" labels=":Item"><data key="labels">:Item</data><data key="itemId">Q23</data></node>

<node id="n406727" labels=":User"><data key="labels">:User</data><data key="hobbies">[Ljava.lang.String;@78ba00a3</data><data key="firstName">a</data><data key="imgPath">/uploads/a.png</data><data key="surName">a</data><data key="username">a</data><data key="gender">Male</data><data key="relaStatus">Single</data></node>
<node id="n406729" labels=":User"><data key="labels">:User</data><data key="hobbies"></data><data key="firstName">b</data><data key="imgPath">/uploads/b.png</data><data key="surName">b</data><data key="username">b</data><data key="gender">Male</data><data key="relaStatus">Single</data></node>
<node id="n406731" labels=":User"><data key="labels">:User</data><data key="hobbies"></data><data key="blocked">[Ljava.lang.String;@7b800b40</data><data key="firstName">c</data><data key="imgPath">/uploads/c.png</data><data key="surName">c</data><data key="username">c</data><data key="gender">Male</data><data key="relaStatus">Single</data></node>

<edge id="e1223400" source="n406727" target="n406729" label="FRIEND_OF"><data key="label">FRIEND_OF</data></edge>
<edge id="e1223403" source="n406727" target="n406731" label="FRIEND_OF"><data key="label">FRIEND_OF</data></edge>
<edge id="e1223405" source="n406734" target="n406731" label="FRIEND_OF"><data key="label">FRIEND_OF</data></edge>

<edge id="e1223374" source="n406727" target="n2" label="HAS_HOBBY"><data key="label">HAS_HOBBY</data></edge>
<edge id="e1223385" source="n406727" target="n51" label="HAS_HOBBY"><data key="label">HAS_HOBBY</data></edge>
<edge id="e1223383" source="n406729" target="n2" label="HAS_HOBBY"><data key="label">HAS_HOBBY</data></edge>
<edge id="e1223384" source="n406731" target="n2" label="HAS_HOBBY"><data key="label">HAS_HOBBY</data></edge>
<edge id="e1223375" source="n406731" target="n51" label="HAS_HOBBY"><data key="label">HAS_HOBBY</data></edge>

</graph>
</graphml>

お時間をいただきありがとうございます。

編集#2:ラベルノードとhasLabelエッジのデータを追加:

<node id="n3" labels=":Label"><data key="labels">:Label</data><data key="en-gb">Universe</data>
<edge id="e0" source="n2" target="n3" label="hasLabel"><data key="label">hasLabel</data></edge>

このエッジは、Q1 の itemId を持つノード n2 を、ラベル「Universe」を持つノード n3 に接続します。

4

2 に答える 2

1

Q: * .. 少なくとも 1 つの趣味を彼と共有しているすべての彼の友人..*
これが最初の可能性です。

ユーザー ID のすべての趣味のエッジで変数を作成します。

<xsl:variable name="hobbies" select="//ns:edge[@source=$USERID and @label='HAS_HOBBY']"/>

すべての友達 (エッジ) に同じ:

<xsl:variable name="friends" select="//ns:edge[@target=$USERID and @label='FRIEND_OF']"/>

同じ趣味の友達より:

<xsl:variable name="friends_with_bobby"
   select="$friends[ //ns:edge[ @label='HAS_HOBBY'  and 
         @target = $hobbies/@target]/@source=./@source   ]"/>

これをテストするには、次を試してください。

<xsl:template match="ns:node[ns:data[@key='username' and . = 'c']]">
    <xsl:copy>
        <xsl:apply-templates select="node()|@*"/>
    </xsl:copy>

    <xsl:variable name="USERID" select="@id"/>

    <xsl:variable name="hobbies" select="//ns:edge[@source=$USERID and @label='HAS_HOBBY']"/>
    <xsl:variable name="friends" select="//ns:edge[@target=$USERID and @label='FRIEND_OF']"/>
    <xsl:variable name="friends_with_bobby" select="$friends[ //ns:edge[ @label='HAS_HOBBY'  and @target = $hobbies/@target]/@source=./@source   ]"/>
    <hobbies>
        <xsl:copy-of select="$hobbies" />
    </hobbies>
    <friends>
        <xsl:copy-of select="$friends" />
    </friends>
    <friends_with_bobby>
        <xsl:copy-of select="$friends_with_bobby" />
    </friends_with_bobby>
</xsl:template>

これは端にすぎませんが、要求された出力に簡単に適応できるはずです。(それ以外の場合はお知らせください)

更新: 同じ趣味を持つすべてのユーザーを取得するには (友達である必要はありません)、次を試してください:

    <xsl:variable name="shared_hobby" select="//ns:edge[ @label='HAS_HOBBY'  and @target = $hobbies/@target]"/>
    <xsl:variable name="n_user_shared_hobby" select="//ns:node[ns:data[@key='username'] and @id=$shared_hobby/@source]"/>
于 2016-03-30T10:50:09.997 に答える