提问人:payne 提问时间:2/9/2019 最后编辑:payne 更新时间:2/9/2019 访问量:288
将 for-each 中的元素 ID 与另一个元素的 ID 匹配
Match an element's ID from within a for-each with another element's ID
问:
对不起,如果我的标题不是很清楚:我很难想出一个恰当的方式来简洁地表达我的问题。
这是我的结构的样子:XML
<library>
<books>
<book writers="007,911">
<title>Two authors wrote me</title>
<price>4.00</price>
</book>
<book writers="911">
<title>Only one here</title>
<price>2.50</price>
</book>
</books>
<authors>
<author id="007">
<name>James</name>
</author>
<author id="911">
<name>Police</name>
</author>
<author id="666">
<name>Diablo</name>
</author>
</authors>
</library>
对于每个作者
,我的目标是:列出他们的孩子(这里我只介绍),但也列出当前匹配至少一个 .如果未找到 -match,则不应显示该特定项的 s 列表。该列表应按所有匹配项的价格降序排序。name
book
id
writers
book
book
author
以下是我到目前为止所做的代码的基本部分:XSLT
<xsl:template match="/"> <!-- I'm skipping all the irrelevant <html> stuff, of course. -->
<body>
<ol>
<xsl:for-each select="//author">
<li>
<b>ID: </b><xsl:value-of select="@id"/>
<ul>
<xsl:call-template name="auth_infos"></xsl:call-template>
<xsl:call-template name="books_stuff"></xsl:call-template>
</ul>
</li>
</xsl:for-each>
</ol>
</body>
</xsl:template>
<xsl:template name="auth_infos">
<li><b>Name: </b><xsl:value-of select="name"/></li>
</xsl:template>
<xsl:template name="books_stuff">
<xsl:if test="//book[//author/@id = @writers]"> <!-- This is supposed to make sure that if the author doesn't have any books listed in the database, then there shouldn't be an empty list of books. Only his name should be presented. -->
<li><b>Book(s): </b>
<xsl:for-each select="//book[//author/@id = @writers]">
<xsl:sort select="price" order="descending"/> <!-- Because I would also like to sort them based on their price. -->
<li><b>Title: </b><xsl:value-of select="//title"/></li>
</xsl:for-each>
</li>
</xsl:if>
</xsl:template>
显然,我对这个特定的 XPath
表达式有问题:.我似乎不明白如何确保我只验证正在迭代的电流 id 的匹配。此外,由于 s 可以有多个( 到 的 id),我不确定如何应用运算符。"//book[//author/@id = @writers]"
author
book
writers
IDREFS
author
contains
结果将是这样的:
-ID: 007
-Name: James
-Book(s):
-Title: Two authors wrote me
-ID: 911
-Name: Police
-Book(s):
-Title: Two authors wrote me
-Title: Only one here
-ID: 666
-Name: Diablo
答:
1赞
michael.hor257k
2/9/2019
#1
假设您仅限于 XSLT 1.0,这将有点尴尬:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" encoding="utf-8"/>
<xsl:template match="/library">
<body>
<ol>
<xsl:for-each select="authors/author">
<xsl:variable name="books" select="../../books/book[contains(concat(',', @writers, ','), concat(',', current()/@id, ','))]"/>
<li>
<b>ID: </b>
<xsl:value-of select="@id"/>
<ul>
<li>
<b>Name: </b>
<xsl:value-of select="name"/>
</li>
<xsl:if test="$books">
<li>
<b>Book(s): </b>
<ul>
<xsl:for-each select="$books">
<xsl:sort select="price" data-type="number" order="descending"/>
<li><b>Title: </b><xsl:value-of select="title"/></li>
</xsl:for-each>
</ul>
</li>
</xsl:if>
</ul>
</li>
</xsl:for-each>
</ol>
</body>
</xsl:template>
</xsl:stylesheet>
应用于您的示例,结果为:
<body><ol>
<li>
<b>ID: </b>007<ul>
<li>
<b>Name: </b>James</li>
<li>
<b>Book(s): </b><ul><li>
<b>Title: </b>Two authors wrote me</li></ul>
</li>
</ul>
</li>
<li>
<b>ID: </b>911<ul>
<li>
<b>Name: </b>Police</li>
<li>
<b>Book(s): </b><ul>
<li>
<b>Title: </b>Two authors wrote me</li>
<li>
<b>Title: </b>Only one here</li>
</ul>
</li>
</ul>
</li>
<li>
<b>ID: </b>666<ul><li>
<b>Name: </b>Diablo</li></ul>
</li>
</ol></body>
呈现为:
评论
0赞
payne
2/9/2019
这行得通。 :有趣的台词,那里!不确定我自己会不会想通。随意添加有关该表达式工作原理的更多细节。我现在也很好奇一个版本会好多少。"../../books/book[contains(concat(',', @writers, ','), concat(',', current()/@id, ','))]"
XSLT 2.0
1赞
michael.hor257k
2/9/2019
@payne 它通过搜索 in - IOW 来工作,无论它在搜索文本中的位置如何,它都会明确地找到搜索字符串。在 XSLT 2.0 中,您可以使用该函数来解析搜索到的文本,然后进行比较,或者(甚至更好)将其用作键。,007,
,007,911,
tokenize()
=
0赞
payne
2/12/2019
我刚刚意识到我的 XML 格式不正确:在同一属性中引用多个 ID 的方法是将它们与 而不是 .:(SPACES ( )
COMMAS (,)
0赞
payne
2/12/2019
它使它变得简单得多!溶液:。谢谢你的帮助。//book[contains(@writers, current()/@id)]
1赞
michael.hor257k
2/12/2019
@payne 使用哪种分隔符并不重要。问题是误报:(例如 包含或 )。仅当所有 ID 的长度相同时,您的解决方案才有效。127
12
27
评论
007
007,911
Oxygen XML Editor 19.1