XSLT,xml 到 xml 无法获得正确的命名空间

XSLT, xml to xml can't get the namespace right

我在将我的 xml 转换为另一个 xml 时遇到了一些问题,我不知道如何将我的命名空间仅添加到我的根元素,它总是在错误的位置添加作者命名空间

我的首发XML

<?xml version="1.0" encoding="utf-8"?>

<library>
    <authors>
        <author id="a1">
            <name>Bob</name>
            <surname>some surname</surname>
            <born>1939-11-11</born>
        </author>
        <author id="a4">
            <name>Rob</name>
            <surname>surname</surname>
            <born>1973-02-19</born>
        </author>
    </authors>
    <books>
        <book id="b1" author-id="a1">
            <title>Some title</title>
            <published>1392</published>
        </book>
        <book id="b2" author-id="a4">
            <title>Some other title</title>
            <published>1743</published>
        </book>
    </books>
</library>

我希望我的输出看起来像什么

<?xml version="1.0" encoding="utf-8"?>
<books xmlns="http://example.net/books/1.0" 
    xmlns:a="http://example.net/author/1.0">
    <book>
        <a:author>
            <a:name>Bob</a:name>
            <a:surname>some surname</a:surname>
        </a:author>
        <title>Some title</title>
    </book>
    <book>
        <a:author>
            <a:name>Rob</a:name>
            <a:surname>surname</a:surname>
        </a:author>
        <title>Some other title</title>
    </book>
</books>

我现在拥有的

<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns="http://example.net/books/1.0"
                xmlns:a="http://example.net/author/1.0"
                >
    <xsl:output method="xml" indent="yes" version="1.0"/>
    <xsl:template match="/">
        <xsl:element name="books">
            <xsl:for-each select="library/books/book">
                <xsl:element name="book">
                    <xsl:variable name="authorId" select="@author-id"/>
                    <xsl:element name="a:author">
                        <xsl:element name="a:name">
                            <xsl:value-of select="../../a:authors/a:author[@id=$authorId]/name"/>
                        </xsl:element>
                        <xsl:element name="a:surname">
                            <xsl:value-of select="../../a:authors/a:author[@id=$authorId]/surname"/>
                        </xsl:element>
                    </xsl:element>
                    <xsl:element name="title">
                        <xsl:value-of select="title"/>
                    </xsl:element>
                </xsl:element>
            </xsl:for-each>
        </xsl:element>
    </xsl:template>
</xsl:stylesheet>

它在错误的元素中给了我我的命名空间(我需要它在书中)

<?xml version="1.0" encoding="utf-8"?>
<books xmlns="http://example.net/books/1.0">
    <book>
        <a:author xmlns:a="http://example.net/author/1.0">
            <a:name>Bob</a:name>
            <a:surname>some surname</a:surname>
        </a:author>
        <title>Some title</title>
    </book>
    <book>
        <a:author>
            <a:name>Rob</a:name>
            <a:surname>surname</a:surname>
        </a:author>
        <title>Some other title</title>
    </book>
</books>

在这种情况下,声明 xmlns:a 命名空间的地方应该没什么区别,但如果你真的希望它在根元素上声明一次,你可以尝试将声明添加到创建中该根元素

<books xmlns:a="http://example.net/author/1.0">

试试这个 XSLT(我也简化了直接写出元素名称而不是使用 xsl:element 并使用键来查找作者)

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns="http://example.net/books/1.0">
    <xsl:output method="xml" indent="yes" version="1.0"/>

    <xsl:key name="authors" match="author" use="@id" />

    <xsl:template match="/">
        <books xmlns:a="http://example.net/author/1.0">
            <xsl:for-each select="library/books/book">
                <book>
                    <xsl:variable name="author" select="key('authors', @author-id)"/>
                    <a:author>
                        <a:name>
                            <xsl:value-of select="$author/name"/>
                        </a:name>
                        <a:surname>
                            <xsl:value-of select="$author/surname"/>
                        </a:surname>
                    </a:author>
                    <title>
                        <xsl:value-of select="title"/>
                    </title>
                </book>
            </xsl:for-each>
        </books>
    </xsl:template>
</xsl:stylesheet>