2014-10-01 3 views
1

Мне нужно написать обширный XSLT, который не выводит (удаляет) любой элемент, который пуст. Для атрибутов это означает, что если значение пути пуст, оно не будет заполнять этот атрибут на выходе. Для узлов это означает, что если данных нет (пустые атрибуты или дочерние узлы без атрибутов/данных), он не будет заполнять этот узел на выходе. Ниже приведен пример, связанный с Бейсболом, чтобы лучше объяснить, что я ищу.XSL Удаление пустых элементов после трансформации

Как выход выглядит сейчас:

<Baseball> 
    <Fields> 
     <Equipment> 
     <Bats> 
      <Bat Brand="Louisville" Model="16534" Length="34" Weight="30" Description="Composite" /> 
      <Bat Brand="Easton" Model="asdfer" Length="32" Weight="29" Description="" /> 
      <Bat Brand="" Model="" Length="" Weight="" Description="" /> 
     </Bats> 
     <Gloves> 
      <Glove Brand="" Model="" Length="" Description="" /> 
     </Gloves> 
     </Equipment> 
    </Fields> 
    </Baseball> 

Как мне нужен выход выглядеть следующим образом:

<Baseball> 
    <Fields> 
     <Equipment> 
     <Bats> 
      <Bat Brand="Louisville" Model="16534" Length="34" Weight="30" Description="Composite" /> 
      <Bat Brand="Easton" Model="asdfer" Length="32" Weight="29" /> 
     </Bats> 
     </Equipment> 
    </Fields> 
    </Baseball> 

Я знаю, что я могу решить эту проблему, написав для проверки значения, но с учетом длина преобразования, я хотел бы избежать этого, если это вообще возможно. Кроме того, укажите структуру XML, из которой я буду рисовать, атрибуты для данного выходного узла будут иметь пути, которые отличаются друг от друга. Например, атрибут «Бренд» в выходном узле «Bat» может иметь путь «ab/cd/ef/brand», тогда как атрибут «Модель» может иметь путь «ab/wx/yz/model». (Я знаю, что мой пример Бейсбола выше не способствует этому). Есть ли способ достичь этого, не написав два XSLT? Можете ли вы пройти через выход в XSLT?

+1

Невозможно сделать второй проход с одним преобразованием, но вы можете написать свой XSLT, чтобы справиться с проблемой аккуратным способом ... у вас есть пример ввода XML, чтобы мы могли продемонстрировать? – JohnLBevan

+0

@JohnLBevan "* Невозможно сделать второй проход с одним преобразованием *" Не уверен, что вы подразумеваете под этим. Вы, безусловно, ** можете ** сделать несколько проходов в пределах одного и того же преобразования (таблица стилей). Вы найдете множество примеров этого, вот только первый, который я выбрал: http://stackoverflow.com/questions/24205393/distinct-values-with-xslt-1-0-when-xpath-has-multiple-criteria/ 24216212 # 24216212 –

+0

@ michael.hor257k - В показанном примере нет нескольких проходов документа. Данные загружаются в переменную, которая затем обрабатывается, но нет никакой настройки шаблона для элементов, сгенерированных другим шаблоном, который соответствует исходному документу. – JohnLBevan

ответ

1

Возможно, тестирование длины атрибутов потомков? Например:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
     version="1.0"> 
     <xsl:template match="*"> 
      <xsl:choose> 
       <xsl:when test="count(descendant-or-self::*/@*) > 0"> 
        <xsl:if test="string-length(descendant-or-self::*/@*) > 0"> 
         <xsl:copy> 
          <xsl:apply-templates select="@*|node()"/> 
         </xsl:copy> 
        </xsl:if> 
       </xsl:when> 
       <xsl:otherwise> 
        <xsl:copy> 
         <xsl:apply-templates select="@*|node()"/> 
        </xsl:copy>  
       </xsl:otherwise> 
      </xsl:choose> 
     </xsl:template> 
     <xsl:template match="@*"> 
      <xsl:if test="string-length(.) > 0"> 
       <xsl:copy/> 
      </xsl:if> 
     </xsl:template> 
    </xsl:stylesheet> 

ПРИМЕЧАНИЕ: Это проверяет длину содержимого атрибутов, а не фактического текста узла. В образце не было и вы можете расширить тестирование.

3

Для достижения вашей цели нет необходимости совершать два прохода. Вам просто нужно добавить шаблоны в существующую таблицу стилей, которая будет соответствовать узлам, не несущим информацию и подавляющим их.

Поскольку вы не показали нам существующую таблицу стилей, в следующем примере применяется только тождественное преобразование на вход как по умолчанию, в то время как два дополнительных шаблонов устранить пустые узлы/ветви:

<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> 

<!-- prune the tree -->  
<xsl:template match="*[not(descendant::text() or descendant-or-self::*/@*[string()])]"/> 
<xsl:template match="@*[not(string())]"/> 

</xsl:stylesheet> 

Applied на ваш текущий выход в качестве тестового ввода, результат будет следующим:

<?xml version="1.0" encoding="UTF-8"?> 
<Baseball> 
    <Fields> 
     <Equipment> 
     <Bats> 
      <Bat Brand="Louisville" Model="16534" Length="34" Weight="30" Description="Composite"/> 
      <Bat Brand="Easton" Model="asdfer" Length="32" Weight="29"/> 
     </Bats> 
     </Equipment> 
    </Fields> 
</Baseball> 
Смежные вопросы