Разница между: child :: node () и child :: * - PullRequest
22 голосов
/ 22 марта 2011

Я только что написал XSLT, который сначала не работал.

Мне пришлось переименовать всех детей от <Recordset> до <C>:

<?xml version="1.0" encoding="utf-8"?>
<Record>
<Recordset>
    <company>102</company>
    <store>1801</store>
    ....
</Recordset>
<Recordset>
....
</Recordset>
</Record>

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

<xsl:template match="Record/Recordset/child::*">    
    <xsl:element name="C">
        <xsl:apply-templates select="@*|node()"/>
    </xsl:element>
</xsl:template>

Работает и переименовывает всех дочерних элементов <Recordset> в <C>. Но сначала мой матч в шаблоне выглядел так:

<xsl:template match="Record/Recordset/child::node()">

Моя идея заключалась в том, что каждый дочерний элемент <Recordset> является узлом, поэтому node() будет уместным. Это тоже сработало, но для каждого ребенка было добавлено <C/>.

В чем разница между child::node() и child::*?

Ответы [ 2 ]

37 голосов
/ 22 марта 2011

child::node() соответствует любому узлу, который не является узлом атрибута, узлом пространства имен или узлом документа. Это означает, что соответствует инструкциям обработки, комментариям и текстовым узлам.

child::* соответствует только элементов.

См. раздел 5.5.3 спецификации:

Узел шаблона () соответствует всем узлам выбирается по выражению root (.) // (child-or-top :: node ()), что есть все элементы, текст, комментарий и узлы инструкций обработки, будь то или нет у них есть родитель. Это не сопоставить атрибут или узлы пространства имен потому что выражение не выбирает узлы, использующие атрибут или пространство имен Оси. Это не соответствует узлам документа потому что для обратной совместимости Причины, по которым ось дочерний или верхний не сопоставить узел документа.

Обновление: Ответ Майкла вдохновил следующую таблицу стилей. Используйте его для проверки типов узлов по мере их обработки:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="/|node()">
        <xsl:call-template name="type" />
        <xsl:text>  [  </xsl:text>
        <xsl:value-of select="." />
        <xsl:text>&#10;</xsl:text>
        <xsl:apply-templates select="node()" />
        <xsl:text>  ]  </xsl:text>
    </xsl:template>
    <xsl:template name="type">
        <xsl:choose>
            <xsl:when test="count(.|/)=1">
                <xsl:text>Root</xsl:text>
            </xsl:when>
            <xsl:when test="self::*">
                <xsl:text>Element </xsl:text>
                <xsl:value-of select="name()" />
            </xsl:when>
            <xsl:when test="self::text()">
                <xsl:text>Text</xsl:text>
            </xsl:when>
            <xsl:when test="self::comment()">
                <xsl:text>Comment</xsl:text>
            </xsl:when>
            <xsl:when test="self::processing-instruction()">
                <xsl:text>PI</xsl:text>
            </xsl:when>
            <xsl:when test="count(.|../@*)=count(../@*)">
                <xsl:text>Attribute</xsl:text>
            </xsl:when>
        </xsl:choose>
    </xsl:template>
</xsl:stylesheet>

Измените то, что соответствует / выбрано, чтобы проверить другие образцы. Например, следующий вход:

<A attr="test" other="val">
  <B/>
  <C>some value</C>
  <!-- a comment -->
  <D/>
</A>

Создает следующий вывод:

Root  [  

  some value



Element A  [  

  some value



Text  [  

  ]  Element B  [  
  ]  Text  [  

  ]  Element C  [  some value
Text  [  some value
  ]    ]  Text  [  

  ]  Comment  [   a comment 
  ]  Text  [  

  ]  Element D  [  
  ]  Text  [  

  ]    ]    ]  

Отдельное спасибо этой странице за то, что я начал тесты типа узла. (Особенно уместно, что там также появляется один из ответов Михаила, сделанный более шести лет назад.)

19 голосов
/ 23 марта 2011

Чтобы расширить ответ lwburk, если ваш XML выглядит следующим образом:

<A>
  <B/>
  <C/>
  <D/>
</A>

Тогда элемент A имеет 7 дочерних узлов;три из них являются элементами, четыре - текстовыми узлами.Выражение child::node() соответствует всем 7, тогда как child::* соответствует только элементам.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...