2017-02-08 3 views
-1

Пример XML:Заменить Удельное значение XML узел с ABC с использованием XSLT

<MAIN> 
    <A> 
     <first_name>Franklin</first_name> 
     <first_name_Previous></first_name_Previous> 
     <formal_name>Franklin Alagala </formal_name> 
     <gender>M</gender> 
     <is_overridden>false</is_overridden> 
    </A> 
    <B> 
     <first_name>Franklin</first_name> 
     <formal_name>Franklin Alagala </formal_name> 
     <gender>M</gender> 
     <gender_Previous></gender_Previous> 
     <is_overridden>false</is_overridden> 
    </B> 
</MAIN> 

Ожидаемый результат:

<MAIN> 
    <A> 
     <first_name>Franklin</first_name> 
     <first_name_Previous>ABCD</first_name_Previous> 
     <formal_name>Franklin Alagala </formal_name> 
     <gender>M</gender> 
     <is_overridden>false</is_overridden> 
    </A> 
    <B> 
     <first_name>Franklin</first_name> 
     <formal_name>Franklin Alagala </formal_name> 
     <gender>M</gender> 
     <gender_Previous>ABCD</gender_Previous> 
     <is_overridden>false</is_overridden> 
    </B> 
</MAIN> 

Хотите заменить узел, который содержит имя, как предыдущий и узел пуст. Однако, если узел содержит имя как предыдущее и присутствует значение, он должен оставить имя как есть.

+3

Где именно вы застряли с этим? –

+0

Добро пожаловать в переполнение стека. Это место, где можно получить помощь при проблемах, поэтому, если вы попробовали кучу вещей и застряли, вы можете получить помощь. Не стоит спрашивать: «Как мне это сделать?». Вам нужно приложить все усилия, чтобы это сделать. Вы можете прочитать http: // stackoverflow.com/help/how-to-ask для получения дополнительной информации – Mikkel

+0

Я могу прочитать xml в xslt, однако я не знаю, как найти узел, имеющий предыдущее имя. Также мне нужно решение в xslt 1.0 –

ответ

0

Я написал код, который работает отлично:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:date="http://exslt.org/dates-and-times" extension-element-prefixes="date"> 
    <xsl:output indent="yes" /> 
    <xsl:template match="@*|node()"> 
     <xsl:copy> 
     <xsl:if test="contains(name(), '_previous')"> 
     <xsl:if test="not(string(.))">PREVIOUS</xsl:if>  
     </xsl:if> 
      <xsl:apply-templates select="@*|node()"/> 
     </xsl:copy> 
    </xsl:template> 
</xsl:stylesheet> 
0

Позвольте мне привести ваше описание немного по-другому, что лучше приводит к ожидаемому решению.

  1. Вы смотрите на каждый дочерний элемент MAIN (A, B и, возможно, CD и так далее), давайте назовем его ведра.

  2. Каждый ковш вы хотите обработать следующим образом:

    • Посмотрите на каждого его дочернего элемента.
    • Если этот элемент не содержит пустой текстовый контент, оставьте его неизменным.
    • В противном случае (этот элемент не имеет никакого текста) читать содержимое элемента с тем же именем но в предыдущем ведра.
    • Если только что прочитанное значение не пустое, установите для текста текущего элемента значение.
    • В противном случае установите содержимое текущего элемента на ABCD.

Тогда можно записать вышеуказанные правила в XSL следующим образом:

<?xml version="1.0" encoding="UTF-8" ?> 
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 
    <xsl:output method="xml" indent="yes" /> 

    <xsl:template match="MAIN/*/*"> 
    <xsl:copy> 
     <xsl:call-template name="proc_node"/> 
    </xsl:copy> 
    </xsl:template> 

    <xsl:template name="proc_node"> 
    <xsl:variable name="thisName" select="name()"/> 
    <xsl:variable name="cnt" select="string-length(.)"/> 
    <xsl:if test="$cnt &gt; 0"> 
     <xsl:value-of select="."/> 
    </xsl:if> 
    <xsl:if test="$cnt = 0"> 
     <xsl:variable name="prevBucket" select="../preceding-sibling::*[1]"/> 
     <xsl:variable name="prevElem" select="$prevBucket/*[name()=$thisName]"/> 
     <xsl:variable name="cnt" select="string-length($prevElem)"/> 
     <xsl:if test="$cnt &gt; 0"> 
     <xsl:value-of select="$prevElem"/> 
     </xsl:if> 
     <xsl:if test="$cnt = 0">ABCD</xsl:if> 
    </xsl:if> 
    </xsl:template> 

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

Я не знаю, как найти узел, имеющий предыдущий в названии.

Try:

*[contains(name(), 'Previous')] 

Если вы хотите еще больше ограничить это пустые элементы, вы можете использовать:

*[contains(name(), 'Previous') and not(node())] 

Обратите внимание, что XML чувствителен к регистру; «previous» - это не то же самое, что «Предыдущий».

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