合并与使用XSLT重构XML文件

时间:2014-05-21 01:40:32

标签: xml xslt

我是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。

1 个答案:

答案 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>