简体   繁体   中英

Copy XML for each specific child node keeping one complete copy for each child node using XSLT?

I have XML similar to below. I want to "recordize", if you will, the xml based on the authors. So for each author child node I want a complete copy of all the xml and just one author child node for each copy. I have gotten close but generate the authors correctly is hanging me up. Any help is appreciated!

SAMPLE:

<root>
    <book>
        <name>
        ... some data
        </name>
        <info>
        ... some data
        </info>
        <authors>
            <author> Author 1</author>
            <author> Author 2</author>
        </authors>
        other nodes
        .
    </book>
</root>
=======================
OUTPUT:
<root>
    <book>
        <name>
        ... some data
        </name>
        <info>
        ... some data
        </info>
        <authors>
            <author>Author 1</author>
        </authors>
        other nodes
        .
    </book>
</root>

<root>
    <book>
        <name>
        ... some data
        </name>
        <info>
        ... some data
        </info>
        <authors>
            <author>Author 2</author>
        </authors>
        other nodes
        .
    </book>
</root>

This is not exactly trivial - try:

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:template match="/root">
    <xsl:copy>
        <xsl:for-each select="book/authors/author">
            <xsl:apply-templates select="ancestor::book">
                <xsl:with-param name="author" select="."/>
            </xsl:apply-templates>
        </xsl:for-each>
    </xsl:copy>
</xsl:template>

<xsl:template match="*">
    <xsl:param name="author"/>
    <xsl:copy>
        <xsl:apply-templates select="node()">
            <xsl:with-param name="author" select="$author"/>
        </xsl:apply-templates>
    </xsl:copy>
</xsl:template>

<xsl:template match="author">
    <xsl:param name="author"/>
    <xsl:if test=".=$author">
        <xsl:copy-of select="."/>
    </xsl:if>
</xsl:template>

</xsl:stylesheet>

Note: if you can use a XSLT 2.0 processor, read up on parameter tunneling; that will make this slightly less complicated.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM