我是XSLT和XPath的新手,我正在努力编写一个样式表来合并两个文件。
对于这个问题,我将使用一个我正在努力的概念的简单例子,而不是我的实际数据。假设我有两个包含单独但相关数据的xml文件。 authors.xml 和 books.xml 。 authors.xml包含一组作者,其中包含一些基本信息,而books.xml包含一系列书籍,其中包含有关它们的信息(包括作者,重要的是)。
我想要一个包含作者集合的结果XML文件 - 但在每个作者元素中,还包含属于该作者的书籍的集合。
到目前为止,我所掌握的最好的方法就是复制每位作者内部的书籍清单,我觉得我甚至可能采取了一种完全奇怪/错误的方法解决问题。我只是开始围绕如何处理样式表。
示例 authors.xml :
<authors>
<author>
<name>Jane Doe</name>
<age>25</age>
</author>
<author>
<name>John Smith</name>
<age>53</age>
</author>
</authors>
示例 books.xml :
<books>
<book>
<title>Flying Kites</title>
<author>Jane Doe</author>
</book>
<book>
<title>XSLT For Dummies</title>
<author>John Smith</author>
</book>
<book>
<title>Running Fast</title>
<author>Jane Doe</author>
</book>
</books>
示例 output.xml :
<authors>
<author>
<name>Jane Doe</name>
<age>25</age>
<books>
<book>
<title>Flying Kites</title>
</book>
<book>
<title>Running Fast</title>
</book>
</books>
</author>
<author>
<name>John Smith</name>
<age>53</age>
<books>
<book>
<title>XSLT For Dummies</title>
</book>
</books>
</author>
</authors>
我还会提供 当前样式表,但我担心它可能会出错:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output encoding="ISO-8859-1" indent="yes" method="xml"/>
<xsl:variable name="books" select="document('books.xml')"/>
<xsl:template match="/">
<authors>
<xsl:apply-templates select="/authors/author"/>
</authors>
</xsl:template>
<xsl:template match="author">
<author>
<name><xsl:value-of select="./name"/></name>
<age><xsl:value-of select="./age"/></age>
<books>
<xsl:apply-templates select="$books/books/book"/>
</books>
</author>
</xsl:template>
<xsl:template match="book">
<!-- How to only copy if correct author? -->
<xsl:copy-of select="."/>
</xsl:template>
</xsl:stylesheet>
我花了几个小时四处搜索,但我发现的任何东西都没有解决我的问题 - 虽然我发现的东西帮助我理解了XSLT和XPath的工作方式都有所改善。
问题here很有帮助,但主要是关于'更新'现有文件的更新数据。对我来说更相关的部分是更新日期,提供的答案实际上并没有这样做 - 而且我自己也无法做到。
我也在/r/learnprogramming上提出了我的问题,但我得到的唯一答案基本上是“XSLT很糟糕。现在就跑开。”
我很少寻求帮助,但是我已经被遗忘了一段时间,甚至没有想到我应该采取什么方法。任何帮助或建议将不胜感激。
如果相关,我使用Saxon 9来处理xslt。
答案 0 :(得分:1)
你快到了。要为每位作者选择图书,请在author
模板中使用谓词。
<xsl:template match="author">
<author>
<xsl:copy-of select="name"/>
<xsl:copy-of select="age"/>
<books>
<xsl:apply-templates select="$books/books/book[author=current()/name]"/>
</books>
</author>
</xsl:template>
您也可以使用copy-of
(如上所示)代替value-of
。
如果您要复制整个节点,则无需更改book
模板中的任何内容,但copy-of
也会包含author
子节点,因此您可能需要做不同的事情:
<xsl:template match="book">
<xsl:copy>
<xsl:copy-of select="title"/>
</xsl:copy>
</xsl:template>