2013-02-16 5 views
1

Мой XSLT:Почему XSLT производит нежелательные результаты

<xsl:template match="node()"> 
    <xsl:apply-templates /> 
</xsl:template> 

<xsl:template match="soapenv:Body//*"> 
    <xsl:element name="{local-name()}"> 
     <xsl:apply-templates select="@* | *" /> 
     <xsl:value-of select="." /> 
    </xsl:element> 
</xsl:template> 

<xsl:template match="soapenv:Body//@*"> 
    <xsl:attribute name="{local-name()}"> 
     <xsl:value-of select="." /> 
    </xsl:attribute> 
</xsl:template> 

Вход:

<soapenv:Body> 
    <Test asdf="asdfasdf"> 
     <Hope>asdf</Hope> 
    </Test> 
</soapenv:Body> 

Выход:

<Test asdf="asdfasdf"> 
    <Hope>asdf</Hope> 
    asdf 
</Test> 

Мои вопросы, почему я получаю дополнительный Asdf текст после Надежда элемент?

ответ

2

Поскольку ваш Test элемента сочетается с <xsl:template match="soapenv:Body//*">, что создает Test элемента на выходе, применяют шаблоны для своих детей (копирование Hope элемента), а затем добавляет текстовый узел, содержащий строковое значение самого Test элемента - это конкатенация всех его потоковых текстовых узлов, в том числе внутри Hope.

Вы можете это исправить, сделав <xsl:value-of> только огонь, когда данный элемент не имеет дочерних элементов, либо обернув его в

<xsl:if test="not(*)"> 

или с помощью отдельного шаблона для soapenv:Body//*[*]

2

Вы похоже, хотят избавиться от пространства имен. (Зачем? На самом деле это не обязательно!)

Рассмотрите более идиоматический подход.

<!-- 1) always try to start off with the identity template --> 
<xsl:template match="node() | @*"> 
    <xsl:copy> 
     <xsl:apply-templates select="node() | @*" /> 
    </xsl:copy> 
</xsl:template> 

<!-- 2) only create templates for nodes that need extra processing --> 
<xsl:template match="soapenv:*"> 
    <xsl:element name="{local-name()}"> 
     <xsl:apply-templates select="node() | @*" /> 
    </xsl:element> 
</xsl:template> 

Результат с входом:

<Body> 
    <Test asdf="asdfasdf"> 
     <Hope>asdf</Hope> 
    </Test> 
</Body> 

Edit: Если вы просто хотите, чтобы начать вывод на содержимое тела, использование:

<xsl:template match="/"> 
    <xsl:apply-templates select="soapenv:Envelope/soapenv:Body/*" /> 
</xsl:template> 
Смежные вопросы