2015-05-26 1 views
1

Рассмотрим XML нижеXSLT 2.0 удалить элементы на основе имени атрибута и добавить набор элементов вместо

<?xml version="1.0" encoding="UTF-8"?> 
<p > 
    <node> 
    <e a="1"/> 
    <e a="2"/> 
    </node> 
    <a> 
    <c value="-3" v="RRR_1"/> 
    <c value="1" v="RRR_2"/> 
    <c value="11" v="v1"/> 
    <c value="12" v="v2"/> 
    </a> 
</p> 

Я хотел бы найти все гр элементы, v значений атрибутов начинаются с RRR и удалить их Тогда Я хотел бы добавить в конце следующие узлы гр

<c value="123" v="RRR_134"/> 
    <c value="456" v="RRR_233"/> 
    <c value="789" v="RRR_900"/> 

Таким образом, окончательный XML выглядит как

<?xml version="1.0" encoding="UTF-8"?> 
<p > 
    <node> 
    <e a="1"/> 
    <e a="2"/> 
    </node> 
    <a> 
    <c value="11" v="v1"/> 
    <c value="12" v="v2"/> 
    <c value="123" v="RRR_134"/> 
    <c value="456" v="RRR_233"/> 
    <c value="789" v="RRR_900"/> 
    </a> 
</p> 

Я написал следующий XSL, чтобы удалить узлы c с атрибутом v, начиная с RRR - однако как мне изменить один и тот же XSL, чтобы также добавить необходимые элементы в конце. Я могу написать еще один лист XSL, но задаюсь вопросом, можно ли это сделать в том же файле XSLT.

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 

    <xsl:template match="/p/a/c[starts-with(@v, 'RRR')]"></xsl:template> 

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

    <!-- remove new lines for a deleted element --> 
    <xsl:template match="*/text()[normalize-space()]"> 
    <xsl:value-of select="normalize-space()"/> 
    </xsl:template> 

</xsl:stylesheet> 

ответ

1

Одним из возможных решений является добавление узлов после последнего c элемента, как это:

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml" encoding="UTF-8" indent="yes" /> 
    <xsl:strip-space elements="*"/> 
    <xsl:template match="/p/a/c[starts-with(@v, 'RRR')]"/> 
    <!-- identity transform --> 
    <xsl:template match="@*|node()"> 
    <xsl:copy> 
     <xsl:apply-templates select="@*|node()"/> 
    </xsl:copy> 
    </xsl:template> 
    <xsl:template match="c[position()=last()]"> 
    <xsl:copy> 
     <xsl:apply-templates select="@*|node()"/> 
    </xsl:copy> 
    <c value="123" v="RRR_134"/> 
    <c value="456" v="RRR_233"/> 
    <c value="789" v="RRR_900"/> 
    </xsl:template> 
</xsl:stylesheet> 

Применительно к вашей входной XML это выводит:

<?xml version="1.0" encoding="UTF-8"?> 
<p> 
    <node> 
    <e a="1"/> 
    <e a="2"/> 
    </node> 
    <a> 
    <c value="11" v="v1"/> 
    <c value="12" v="v2"/> 
    <c value="123" v="RRR_134"/> 
    <c value="456" v="RRR_233"/> 
    <c value="789" v="RRR_900"/> 
    </a> 
</p> 

I» ve также удалил шаблон для удаления новых строк для удаленных элементов и добавил <xsl:strip-space elements="*"/> вместо этого и xsl:output с атрибутом indent="yes" для про duce с отступом.
Шаблон, соответствующий последнему элементу c, копирует этот элемент и только затем записывает дополнительные c узлы.

+0

Perfect - спасибо @matthias_h! –

Смежные вопросы