开发者

XSLT - rearrange all child elements under the first parent element

I need to rearrange all the the child elements of an XML Document underneath the first Parent (and discard all other parent info)

In the example below, I need all 4 child elements under Parent[ParentField=1] and discard Parent[ParentField=X]

<xml>
    <Parent>
        <ParentField>1</ParentField>
        <Children>
            <Child>
                <id>1</id>
            </Child>
            <Child>
                <id>2</id>
            </Child>
        </Children>
    </Parent>
    <Parent>
   开发者_开发问答     <ParentField>X</ParentField>
        <Children>
            <Child>
                <id>3</id>
            </Child>
            <Child>
                <id>4</id>
            </Child>
        </Children>
    </Parent>
</xml>

Resulting in XML like so:

<xml>
    <Parent>
        <ParentField>1</ParentField>
        <Children>
            <Child>
                <id>1</id>
            </Child>
            <Child>
                <id>2</id>
            </Child>
            <Child>
                <id>3</id>
            </Child>
            <Child>
                <id>4</id>
            </Child>
        </Children>
    </Parent>
</xml>


This stylesheet:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:param name="pParentField" select="1"/>
    <xsl:template match="node()|@*" name="identity">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="Parent">
        <xsl:if test="ParentField = $pParentField">
            <xsl:call-template name="identity"/>
        </xsl:if>
    </xsl:template>
    <xsl:template match="Children">
        <xsl:copy>
            <xsl:apply-templates select="/xml/Parent/Children/Child"/>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

Output:

<xml>
    <Parent>
        <ParentField>1</ParentField>
        <Children>
            <Child>
                <id>1</id>
            </Child>
            <Child>
                <id>2</id>
            </Child>
            <Child>
                <id>3</id>
            </Child>
            <Child>
                <id>4</id>
            </Child>
        </Children>
    </Parent>
</xml>


FWIW the following also seems to work, but looks really 'orrible. Alejandro's solution is more elegant.

<xsl:template match="/">
    <xsl:apply-templates select="xml" />
</xsl:template>
<xsl:template match="xml">
    <Parent>
        <xsl:for-each select="Parent[1]">
            <ParentField><xsl select...><ParentField>
        </xsl:for-each>
        <Children>
        <xsl:for-each select="//Child">
            <Child>
                <...>
            </Child>
        </xsl:for-each>
    </Parent>
</xsl:template>

Edit : Alejandro's comment inline for purpose of formatting :)

Push style is not a bad solution when you know your schema. But I think it would be better:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:param name="pParentField" select="1"/>
    <xsl:template match="/">
      <xml>
        <Parent>
          <xsl:copy-of select="Parent[ParentField=$pParentField]"/>
          <Children>
            <xsl:copy-of select="/xml/Parent/Children/Child"/>
          </Children>
        </Parent>
      </xml>
    </xsl:template>
 </xsl:stylesheet>
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜