2016-02-21 3 views
2

Это мой вход:XSLT выбрать только элементы с заданным значением

<div class="z">zzz 
    <div class="a">a1</div> 
    <div class="b">b1 
    <div class="c">b1c1 
     <div class="d">b1c1d1</div> 
     <div class="e">b1c1e1</div> 
     <div class="f">b1c1f1</div> 
    </div> 
    <div class="c">b1c2 
     <div class="d">b1c2d1</div> 
     <div class="e">b1c2e1</div> 
     <div class="f">b1c2f1</div> 
     <div class="f">b1c2f2</div> 
    </div> 
    </div> 
    <div class="b">b2 
    <div class="c">b2c1 
     <div class="d">b2c1d1</div> 
     <div class="e">b2c1e1</div> 
     <div class="e">b2c1e2</div> 
     <div class="f">b2c1f1</div> 
    </div> 
    </div> 
</div> 

и это выход, я хотел бы получить:

<div class="z">zzz 
    <div class="a">a1</div> 
    <div class="b">b1 
    <div class="c">b1c1 
     <div class="d">b1c1d1</div> 
     <div class="e">b1c1e1</div> 
     <div class="f">b1c1f1</div> 
    </div> 
    <div class="c">b1c2 
     <div class="d">b1c2d1</div> 
     <div class="e">b1c2e1</div> 
     <div class="f">b1c2f1</div> 
     <div class="f">b1c2f2</div> 
    </div> 
    </div> 
</div> 

, который я хотел бы получить:

  • любой текст для сНу класса = "г", т.е. "ZZZ"
  • любой ребенок, который имеет класс! = "Ъ"
  • любой ребенок, который имеет класс = "Ъ" и значение = "b1"

Я использую следующий XSLT:

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

<!-- Identity template, copies everything as is --> 
<xsl:template match="@*|node()"> 
    <xsl:copy> 
    <xsl:apply-templates select="@*|node()"/> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="div[@class='z']"> 
    <xsl:apply-templates select="div[@class='b' and text()='b1']" /> 
</xsl:template> 

</xsl:stylesheet> 

, но, к сожалению, мой выход пуст :(

Что я сделал не так?

Благодарим за помощь.

ответ

3

Основная проблема заключается в том, что текстовый узел для «b1» также содержит пробелы. За «b1» следует строка и некоторые пробелы, поэтому ваша текущая проверка на текстовом узле не работает. Для удовлетворения этого, вы можете использовать функцию normalize-space, которая будет обрезать пробелы из концов (это будет также объединить несколько символов пробела в середине текста в единое пространство, если таковые присутствуют)

<xsl:apply-templates select="div[@class='b' and normalize-space(text())='b1']" /> 

Это, по крайней мере, даст вам некоторый результат, но вы также обнаружите, что div класса «z» не отображается в выводе. Это связано с тем, что, сопоставив div, вы должны явно скопировать узел на вывод вместе со всеми дочерними узлами и атрибутами. В настоящее время вы просто выбираете divs с классом «b», а не что-то еще.

Таким образом, ваш xsl:apply-templates действительно должны выглядеть следующим образом:

<xsl:apply-templates select="@*|text()|div[(@class='b' and normalize-space(text())='b1') or @class != 'b']" /> 

Однако, вы можете посмотреть на проблему с другой точки зрения. Вместо того, чтобы писать правила для того, что вы хотите скопировать, напишите правила для того, что вы не хотите копировать, и создайте шаблоны, чтобы игнорировать такие узлы. Шаблон идентичности позаботится о том, чтобы копировать все, что вам нужно.

Попробуйте XSLT вместо:

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

<!-- Identity template, copies everything as is --> 
<xsl:template match="@*|node()"> 
    <xsl:copy> 
    <xsl:apply-templates select="@*|node()"/> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="div[@class='b' and normalize-space(text())!='b1']" /> 

</xsl:stylesheet> 
+0

О, что делает его проще. Спасибо Тиму. – Yalmar

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