XSLT - переставить все дочерние элементы под первым родительским элементом - PullRequest
0 голосов
/ 22 октября 2010

Мне нужно переставить все дочерние элементы XML-документа под первым родителем (и отбросить всю другую родительскую информацию)

В приведенном ниже примере мне нужны все 4 дочерних элемента в разделе Parent [ParentField =1] и сбросить 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>

В результате XML выглядит так:

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

Ответы [ 2 ]

2 голосов
/ 22 октября 2010

Эта таблица стилей:

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

Вывод:

<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>
0 голосов
/ 22 октября 2010

FWIW следующее также, кажется, работает, но выглядит действительно «ужасно». Решение Алехандро более элегантно.

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

Редактировать: комментарий Алехандро, встроенный в целях форматирования:)

Стиль Push не является плохим решением, когда вы знаете свою схему. Но я думаю, что было бы лучше:

<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>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...