2016-07-20 1 views
0

Я пытаюсь преобразовать данный XML с помощью xslt. Предостережение заключается в том, что мне пришлось бы удалить родительский узел, если данный дочерний узел отсутствует. Я сделал несколько шаблонов, но я застрял. Любая помощь будет оценена по достоинству.Удалить родительский узел, если дочерний узел пуст

Входной XML:

<?xml version="1.0" encoding="UTF-8"?> 
<main> 
    <item> 
     <value> 
      <item> 
       <value>ABC</value> 
       <key>test1</key> 
      </item> 
      <item> 
       <value>XYZ</value> 
       <key>test2</key> 
      </item> 
       <item> 
       <value></value> 
       <key>test3</key> 
      </item> 
     </value> 
    </item> 
    <item> 
     <value /> 
     <key>test4</key> 
    </item> 
    <item> 
     <value>PQR</value> 
     <key>test5</key> 
    </item> 
</main> 

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

<?xml version="1.0" encoding="UTF-8"?> 
<main> 
    <item> 
     <value> 
      <item> 
       <value>ABC</value> 
       <key>test1</key> 
      </item> 
      <item> 
       <value>XYZ</value> 
       <key>test2</key> 
      </item> 
     </value> 
    </item> 
    <item> 
     <value>PQR</value> 
     <key>test5</key> 
    </item> 
</main> 

Проблема, если я использовать шаблон, соответствующий, например,

<xsl:template match="item[not(value)]"/> как указано в deleting the parent node if child node is not present in xml using xslt, тогда он полностью удаляет все, так как основной/элемент/значение также пуст.

Мне нужно удалить, если элемент пуст, но только если элемент не имеет дочернего элемента.

+0

Кроме того, если значение для ключа test1 и test2 пустое, элемент верхнего уровня также должен быть исключен из вывода. – Ady211

ответ

1

Вы должны сначала начать с шаблоном идентичности XSLT

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

Тогда все, что вам нужно, это шаблон, который соответствует item элемент, где все Потомок лист value элементы пустые.

<xsl:template match="item[not(descendant::value[not(*)][normalize-space()])]" /> 

Таким образом, шаблон соответствует ему, но не выводит его.

Попробуйте XSLT

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

    <xsl:template match="item[not(descendant::value[not(*)][normalize-space()])]" /> 

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

Это работает как шарм. Как этот xslt отличается от основного/элемента/значения (который пуст и имеет элемент дочернего узла) от элемента/значения? Неужели (*) не делает трюк? – Ady211

+0

Да. Выполнение 'not (*)' проверяет отсутствие дочерних элементов, поэтому оно будет соответствовать только элементам "leaf". –

0

Я думаю, что вы хотите удалить элемент из него, не имеет детей вообще (будь то дети являются элементами или текстовыми узлами). Попробуйте вставить этот шаблон:

<xsl:template match="item"> 
 
    <xsl:if test="exists(value/node())"> 
 
     <xsl:copy> 
 
      <xsl:copy-of select="@*"/> 
 
      <xsl:apply-templates/> 
 
     </xsl:copy> 
 
    </xsl:if> 
 
</xsl:template>

+0

Я пробовал, что он не работает и дает ошибку компиляции xslt. Ошибка: XSLTProcessor :: transformToXml(): xmlXPathCompiledEval: осталось 1 объект в стеке. – Ady211

+0

@ Ady211 Вы уверены, что используете XSLT 2.0, как указывает тег на ваш вопрос? –

+0

Я использую xslt 1.0. – Ady211

0

Если я прочитал это правильно, что вы хотите сделать:

XSLT 1,0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/> 
<xsl:strip-space elements="*"/> 

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

<xsl:template match="item[not(value[node()])]"/> 

</xsl:stylesheet> 

Это позволит удалить item что не имеет value ребенок с некоторые содержание.