Как отсортировать родительские элементы только по их корневым узлам в XSLT? - PullRequest
0 голосов
/ 24 мая 2019

Я получил XML-файл, похожий на

<root>
<number>1</number>
<number>
    <deleted>0</deleted>
    3
</number>
<number>2</number>
</root>

Я хочу отсортировать файл только по допустимому значению, например, допустимое значение второго элемента равно 3. Мне нужно только значение, не содержащееся ни в каких дочерних элементах. Таким образом, желаемый результат выглядит так:

<root>
<number>1</number>
<number>2</number>
<number>
 <deleted>0</deleted>
 3
</number>
</root>

Я пытался использовать except в сортировке, но это не сработало. Моя таблица стилей:

    <xsl:template match="root">
        <xsl:copy>
            <xsl:for-each select="number">
                <xsl:sort select=". except del"/>
                <xsl:copy-of select="." />
            </xsl:for-each>
        </xsl:copy>
    </xsl:template>

Спасибо!

Добавить: Я изменил XML на

<root>
    <number>1</number>
    <number>
        1
        <deleted>0</deleted>
        3
    </number>
    <number>2</number>
</root>

Вставьте узел перед тегом <deleted>, тогда <xsl:sort select="text()"> не может работать. Сообщение об ошибке говорит XTTE1020: A sequence of more than one item is not allowed as the @select attribute of xsl:sort (text("1"), text("3")) Пожалуйста, помогите: (

1 Ответ

1 голос
/ 24 мая 2019

. соответствует текущему узлу, который равен number, поэтому выполнение . except deleted на самом деле многого не даст.Вам нужно отсортировать по дочернему узлу, который не является deleted

 <xsl:sort select="node() except deleted" data-type="number" />

Хотя на самом деле вам нужен только текстовый узел, так что вам вообще не нужно except вообще

<xsl:sort select="text()" data-type="number" />

Однако это будет работать только в том случае, если сначала вы удаляете узлы пробелов с помощью xsl:strip-space (в противном случае вы получите ошибку о сортировке, выбирающей последовательность узлов).В качестве альтернативы вы можете сделать <xsl:sort select="text()[normalize-space()]" data-type="number" />

Попробуйте этот XSLT

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
  <xsl:strip-space elements="*" />

  <xsl:output method="xml" indent="yes" />

  <xsl:template match="root">
    <xsl:copy>
      <xsl:for-each select="number">
        <xsl:sort select="text()" data-type="number" />
        <xsl:copy-of select="." />
      </xsl:for-each>
    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>

Обратите внимание, что приведенная выше таблица стилей будет работать в XSLT 1.0, но если вы используете XSLT 2.0, то вы можете упростить это:бит с xsl:perform-sort вместо ...

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
  <xsl:strip-space elements="*" />

  <xsl:output method="xml" indent="yes" />

  <xsl:template match="root">
    <xsl:copy>
      <xsl:perform-sort select="number">
        <xsl:sort select="text()" data-type="number" />
      </xsl:perform-sort>
    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>

РЕДАКТИРОВАТЬ: И, если у вас есть несколько дочерних текстовых узлов, то сделать это, чтобы объединить их ...

<xsl:sort select="string-join(text()/normalize-space())" data-type="number" />
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...