Xslt для переименования списка - PullRequest
1 голос
/ 07 сентября 2010

У меня есть этот XML:

<Root>
    <Tag>
        <Childlist>
            <I>1</I>
            <Dlist>2</Dlist>
            <Dlist>3</Dlist>
            <Dlist>4</Dlist>
        </Childlist>
        <Childlist>
            <I>11</I>
            <Dlist>2</Dlist>
            <Dlist>3</Dlist>
            <Dlist>4</Dlist>
        </Childlist>
    </Tag>
</Root>

и я хочу преобразовать это в:

<Root>
    <Tag>
        <Childlist>
            <item>
                <I>1</I>
                <Dlist>
                    <item>2</item>
                    <item>3</item>
                    <item>4</item>
                </Dlist>
            </item>
            <item>
                <I>11</I>
                <Dlist>
                    <item>2</item>
                    <item>3</item>
                    <item>4</item>
                </Dlist>
            </item>
        </Childlist>
    </Tag>
</Root>

с использованием XSLT. Как вы можете видеть, повторяющиеся теги в первом XML заменяются тегом, а тег списка создается как родительский тег.

Кто-нибудь может посоветовать xslt для этого преобразования?

Заранее спасибо.

Редактировать : из комментариев.

У меня проблема с this xls. Если я добавлю любой тег ниже Dlist, он получит добавлен в список

Будут другие предшествующие и следующие элементы [из Dlist]

Ответы [ 2 ]

1 голос
/ 08 сентября 2010

Помимо превосходного ответа Димитра, эта таблица стилей:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()[1]|@*"/>
        </xsl:copy>
        <xsl:apply-templates select="following-sibling::node()[1]"/>
    </xsl:template>
    <xsl:template match="Tag">
        <Tag>
            <Childlist>
                <xsl:apply-templates select="node()[1]"/>
            </Childlist>
        </Tag>
    </xsl:template>
    <xsl:template match="*/Dlist[1]">
        <xsl:copy>
            <xsl:call-template name="makeItem"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="Childlist|Dlist" name="makeItem">
        <Item>
            <xsl:apply-templates select="node()[1]"/>
        </Item>
        <xsl:apply-templates select="following-sibling::node()[1]"/>
    </xsl:template>
</xsl:stylesheet>

Выход:

<Root>
    <Tag>
        <Childlist>
            <Item>
                <I>1</I>
                <Dlist>
                    <Item>2</Item>
                    <Item>3</Item>
                    <Item>4</Item>
                </Dlist>
            </Item>
            <Item>
                <I>11</I>
                <Dlist>
                    <Item>2</Item>
                    <Item>3</Item>
                    <Item>4</Item>
                </Dlist>
            </Item>
        </Childlist>
    </Tag>
</Root>

Редактировать : С этим вводом:

<Root>
    <Tag>
        <Childlist>
            <I>1</I>
            <Dlist>2</Dlist>
            <Dlist>3</Dlist>
            <Dlist>4</Dlist>
            <F>1</F>
        </Childlist>
        <Childlist>
            <I>11</I>
            <Dlist>2</Dlist>
            <Dlist>3</Dlist>
            <Dlist>4</Dlist>
            <F>11</F>
        </Childlist>
    </Tag>
</Root>

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

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()[1]|@*"/>
        </xsl:copy>
        <xsl:apply-templates select="following-sibling::node()[1]"/>
    </xsl:template>
    <xsl:template match="Tag">
        <Tag>
            <Childlist>
                <xsl:apply-templates select="node()[1]"/>
            </Childlist>
        </Tag>
    </xsl:template>
    <xsl:template match="*/Dlist[last()]" name="makeItem">
        <Item>
            <xsl:apply-templates select="node()[1]"/>
        </Item>
    </xsl:template>
    <xsl:template match="*/Dlist[1]">
        <xsl:copy>
            <xsl:call-template name="wrap"/>
        </xsl:copy>
        <xsl:apply-templates select="following-sibling::node()
                                         [not(self::Dlist)][1]"/>
    </xsl:template>
    <xsl:template match="Childlist|Dlist" name="wrap">
        <xsl:call-template name="makeItem"/>
        <xsl:apply-templates select="following-sibling::node()[1]"/>
    </xsl:template>
</xsl:stylesheet>

Выход:

<Root>
    <Tag>
        <Childlist>
            <Item>
                <I>1</I>
                <Dlist>
                    <Item>2</Item>
                    <Item>3</Item>
                    <Item>4</Item>
                </Dlist>
                <F>1</F>
            </Item>
            <Item>
                <I>11</I>
                <Dlist>
                    <Item>2</Item>
                    <Item>3</Item>
                    <Item>4</Item>
                </Dlist>
                <F>11</F>
            </Item>
        </Childlist>
    </Tag>
</Root>

Примечание : Предполагается, что Dlist элементы - все следующие братья и сестры. Так Dlist[1] открывает новый уровень и после этого применяет шаблоны к следующему узлу Dlist, а Dlist[last()] закрывает уровень, не применяя шаблоны к следующему брату.

0 голосов
/ 07 сентября 2010

Это преобразование :

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:key name="kDlist" match="Dlist"
 use="generate-id((.|preceding-sibling::Dlist)[1])"/>

 <xsl:template match="node()|@*">
  <xsl:copy>
   <xsl:apply-templates select="node()|@*"/>
  </xsl:copy>
 </xsl:template>

 <xsl:template match="*[Childlist]">
  <xsl:copy>
   <xsl:copy-of select="@*"/>
   <Childlist>
    <xsl:apply-templates/>
   </Childlist>
  </xsl:copy>
 </xsl:template>

 <xsl:template match="Childlist|Dlist" name="makeItem">
  <Item>
   <xsl:apply-templates/>
  </Item>
 </xsl:template>

 <xsl:template match="Dlist[not(preceding-sibling::Dlist)]">
  <Dlist>
   <xsl:apply-templates select="key('kDlist', generate-id())" mode="copy"/>
  </Dlist>
 </xsl:template>

 <xsl:template match="Dlist" mode="copy">
  <xsl:call-template name="makeItem"/>
 </xsl:template>

 <xsl:template match="Dlist"/>
</xsl:stylesheet>

применительно к этому документу XML (исходный текст исправлен, чтобы быть корректным):

<Root>
    <Tag>
        <Childlist>
            <I>1</I>
            <Dlist>2</Dlist>
            <Dlist>3</Dlist>
            <Dlist>4</Dlist>
        </Childlist>
        <Childlist>
            <I>11</I>
            <Dlist>2</Dlist>
            <Dlist>3</Dlist>
            <Dlist>4</Dlist>
        </Childlist>
    </Tag>
</Root>

дает желаемый, правильный результат :

<Root>
    <Tag>
        <Childlist>
            <Item>
                <I>1</I>
                <Dlist>
                    <Item>2</Item>
                    <Item>3</Item>
                    <Item>4</Item>
                </Dlist>
            </Item>
            <Item>
                <I>11</I>
                <Dlist>
                    <Item>2</Item>
                    <Item>3</Item>
                    <Item>4</Item>
                </Dlist>
            </Item>
        </Childlist>
    </Tag>
</Root>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...