XSLT - 不能在复杂的图形表示中只复制一次元素
XSLT - cant copy elements only once in complexed graph representation
我有 XML 数据 (GraphML) 我需要为我的应用程序转换。
XML 代表一个图,它有标签 "User" 和 "Item" 的节点,以及标签 "HAS_HOBBY" 和 "FRIEND_OF".
的边
给定一个特定的用户,我想在转换后得到他所有至少与他有一个爱好的朋友,以及那些爱好(用项目表示)。
"friends" 由 "FRIEND_OF" 边缘元素表示,爱好由 "HAS_HOBBY".
表示
我有我的 XSLT(我对此有点陌生)可以找到所需的物品和朋友,但是按照我的逻辑,我不能设法只复制一次朋友 - 他的每个爱好都完成一次与原始用户共享。
我通过为每个用户的爱好检查每个朋友的爱好来做到这一点,当有匹配项时 - 我打印项目(爱好)(没关系)和朋友 - 但是每次匹配都会打印这个朋友被找到,导致这个朋友多次出现,这是不希望的。
我尝试寻找避免这种情况的方法,但我认为我实施此解决方案的整个逻辑都存在缺陷。不过我没有其他想法。
这是我的 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>
目前朋友的副本丢失了,但它会在 "Shared hobby with friend" 评论之后。
我意识到我不能使用 'flag' 类型的变量(因为它不可能..)并且没有办法拥有数组或一些类似的数据结构,所以我真的没有想法。
请帮助我获取与用户分享至少一个爱好(项目)的朋友,以及爱好本身。
编辑:
示例输入:我还添加了图形可视化,因此很容易看到
<?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,边a-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。
问:* ..所有与他有至少一种爱好的朋友..*
这是第一种可能性。
为用户 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]"/>
这是一个使用 XSLT 2.0(受 Saxon 9、XmlPrime、Altova、Exselt 支持)的示例,使用键引用项目,然后将 intersect
等操作设置为仅输出共享节点:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs"
xpath-default-namespace="http://graphml.graphdrawing.org/xmlns"
version="2.0">
<xsl:param name="user-name" as="xs:string" select="'c'"/>
<xsl:output indent="yes"/>
<xsl:key name="user-name" match="node[@labels = ':User']" use="data[@key = 'username']"/>
<xsl:key name="node-id" match="node" use="@id"/>
<xsl:key name="source-friends" match="edge[@label = 'FRIEND_OF']" use="@source"/>
<xsl:key name="target-friends" match="edge[@label = 'FRIEND_OF']" use="@target"/>
<xsl:key name="source-hobbies" match="edge[@label = 'HAS_HOBBY']" use="@source"/>
<xsl:variable name="start-node" select="key('user-name', $user-name)"/>
<xsl:variable name="start-friends"
select="key('node-id', key('source-friends', $start-node/@id)/@target) |
key('node-id', key('target-friends', $start-node/@id)/@source)"/>
<xsl:variable name="start-hobbies" select="key('node-id', key('source-hobbies', $start-node/@id)/@target)"/>
<xsl:variable name="friends-with-shared-hobby" select="$start-friends[key('node-id', key('source-hobbies', @id)/@target) intersect $start-hobbies]"/>
<xsl:variable name="shared-hobbies" select="$start-hobbies intersect key('node-id', key('source-hobbies', $friends-with-shared-hobby/@id)/@target)"/>
<xsl:template match="/*">
<xsl:copy>
<xsl:copy-of select="$start-node | $friends-with-shared-hobby | $shared-hobbies"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
我有 XML 数据 (GraphML) 我需要为我的应用程序转换。 XML 代表一个图,它有标签 "User" 和 "Item" 的节点,以及标签 "HAS_HOBBY" 和 "FRIEND_OF".
的边给定一个特定的用户,我想在转换后得到他所有至少与他有一个爱好的朋友,以及那些爱好(用项目表示)。 "friends" 由 "FRIEND_OF" 边缘元素表示,爱好由 "HAS_HOBBY".
表示我有我的 XSLT(我对此有点陌生)可以找到所需的物品和朋友,但是按照我的逻辑,我不能设法只复制一次朋友 - 他的每个爱好都完成一次与原始用户共享。 我通过为每个用户的爱好检查每个朋友的爱好来做到这一点,当有匹配项时 - 我打印项目(爱好)(没关系)和朋友 - 但是每次匹配都会打印这个朋友被找到,导致这个朋友多次出现,这是不希望的。
我尝试寻找避免这种情况的方法,但我认为我实施此解决方案的整个逻辑都存在缺陷。不过我没有其他想法。
这是我的 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>
目前朋友的副本丢失了,但它会在 "Shared hobby with friend" 评论之后。
我意识到我不能使用 'flag' 类型的变量(因为它不可能..)并且没有办法拥有数组或一些类似的数据结构,所以我真的没有想法。
请帮助我获取与用户分享至少一个爱好(项目)的朋友,以及爱好本身。
编辑: 示例输入:我还添加了图形可视化,因此很容易看到
<?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,边a-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。
问:* ..所有与他有至少一种爱好的朋友..*
这是第一种可能性。
为用户 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]"/>
这是一个使用 XSLT 2.0(受 Saxon 9、XmlPrime、Altova、Exselt 支持)的示例,使用键引用项目,然后将 intersect
等操作设置为仅输出共享节点:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs"
xpath-default-namespace="http://graphml.graphdrawing.org/xmlns"
version="2.0">
<xsl:param name="user-name" as="xs:string" select="'c'"/>
<xsl:output indent="yes"/>
<xsl:key name="user-name" match="node[@labels = ':User']" use="data[@key = 'username']"/>
<xsl:key name="node-id" match="node" use="@id"/>
<xsl:key name="source-friends" match="edge[@label = 'FRIEND_OF']" use="@source"/>
<xsl:key name="target-friends" match="edge[@label = 'FRIEND_OF']" use="@target"/>
<xsl:key name="source-hobbies" match="edge[@label = 'HAS_HOBBY']" use="@source"/>
<xsl:variable name="start-node" select="key('user-name', $user-name)"/>
<xsl:variable name="start-friends"
select="key('node-id', key('source-friends', $start-node/@id)/@target) |
key('node-id', key('target-friends', $start-node/@id)/@source)"/>
<xsl:variable name="start-hobbies" select="key('node-id', key('source-hobbies', $start-node/@id)/@target)"/>
<xsl:variable name="friends-with-shared-hobby" select="$start-friends[key('node-id', key('source-hobbies', @id)/@target) intersect $start-hobbies]"/>
<xsl:variable name="shared-hobbies" select="$start-hobbies intersect key('node-id', key('source-hobbies', $friends-with-shared-hobby/@id)/@target)"/>
<xsl:template match="/*">
<xsl:copy>
<xsl:copy-of select="$start-node | $friends-with-shared-hobby | $shared-hobbies"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>