XSL-проверка, чтобы увидеть, имеет ли какой-либо дочерний узел атрибут - PullRequest
3 голосов
/ 28 января 2012

У меня есть следующий XML:

<record>
  <d989 p="Apples" t="Apples"/>
  <d990 p="Oranges" t="Bananas"/>
  <record_group_1>
    <d991 p="Mouse" t="Mouse and Cat"/>
    <d991 p="Dog" t="Dog and Cat"/>
  </record_group_1>
  <record_group_2>
    <d992 />
  </record_group_2>
 ...

и я использую следующий шаблон XSL после определения наличия у узла дочерних элементов:

<xsl:template name="hasChildren">
  <tr>
    <td colspan="2" class="sectionTitle">
      <xsl:value-of select="translate(local-name(), '_', ' ')" />
    </td>
  </tr>
 ...

Как мне обернуть содержимое <xsl:template name="hasChildren">, чтобы определить, имеет ли рассматриваемый узел, имеющий дочерние элементы, атрибут любого из дочерних элементов p.

Я проверяю, есть ли у текущего узла атрибут p с <xsl:if test="@p">, но я не уверен, как я могу найти, если у дочерних узлов узла есть p.

Для приведенного выше примера XML я бы хотел проигнорировать <record_group_2>, потому что его дочерние элементы не содержат атрибута p, где как <record_group_1> я бы хотел обработать.

Если вам нужно больше разъяснений, дайте мне знать ...

Ответы [ 2 ]

1 голос
/ 28 января 2012

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

<xsl:template name="hasChildren">
    <tr>
        <td colspan="2" class="sectionTitle">
            <xsl:value-of select="translate(local-name(), '_', ' ')" />
        </td>
    </tr>  ...
</xsl:template>

Этот код не выполняет то, что, как говорят, делает!

I'm testing if the current node has an attribute of `p` with `<xsl:if test="@p">` but I'm not sure how I could find if the node's children has a `p`.

Используйте

*[@p]

Это выражение XPath выбирает любой дочерний элемент (текущего узла), имеющий атрибут p. При использовании в атрибуте test <xsl:if> или <xsl:when> выбранный набор узлов преобразуется в логическое значение: true(), если набор узлов не пуст, и false() в противном случае.

Для приведенного выше примера XML я бы хотел игнорировать <record_group_2> потому что это дети не содержат атрибут р, где как <record_group_1> Я бы хотел обработать

Используйте : только вышеприведенное выражение.

Вот полное и очень простое и короткое преобразование , которое копирует на выход только те дочерние элементы верхнего элемента, которые имеют атрибут p:

<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="*"/>

 <xsl:template match="/*">
  <xsl:copy>
   <xsl:copy-of select="*[*/@p]"/>
  </xsl:copy>
 </xsl:template>
</xsl:stylesheet>

Когда это преобразование применяется к предоставленному документу XML (исправлено, чтобы оно было правильно сформировано):

<record>
    <d989 p="Apples" t="Apples"/>
    <d990 p="Oranges" t="Bananas"/>
    <record_group_1>
        <d991 p="Mouse" t="Mouse and Cat"/>
        <d991 p="Dog" t="Dog and Cat"/>
    </record_group_1>
    <record_group_2>
        <d992 />
    </record_group_2>
</record>

требуемый, правильный результат (удаляются не верхние элементы, у которых хотя бы один дочерний элемент не имеет атрибута p) * Производится 1048 * :

<record>
   <record_group_1>
      <d991 p="Mouse" t="Mouse and Cat"/>
      <d991 p="Dog" t="Dog and Cat"/>
   </record_group_1>
</record>
1 голос
/ 28 января 2012

Это выражение:

*[starts-with(local-name(), 'record_group_') and *[@p]]

... соответствует всем элементам, чье имя начинается с record_group_ и которые имеют дочерний элемент с атрибутом p (*[@p]).

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

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output omit-xml-declaration="yes" indent="yes"/>
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
    <!-- ignore other elements -->
    <xsl:template match="/*/*"/>
    <xsl:template match="*[starts-with(local-name(), 'record_group_') 
                              and *[@p]]">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

Вывод:

<record>
    <record_group_1>
        <d991 p="Mouse" t="Mouse and Cat"/>
        <d991 p="Dog" t="Dog and Cat"/>
    </record_group_1>
</record>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...