Сортировка узлов XML по дочерним узлам, а затем сортировка разных дочерних узлов - PullRequest
0 голосов
/ 25 июня 2018

Я пытаюсь создать файл XSLT, который будет создавать новый XML из исходного XML, который будет сортировать узлы типов по имени, а затем сортировать элементы внутри каждого типа.

Источник:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
    <types>
        <members>Ontario</members>
        <members>Quebec</members>
        <members>Alberta</members>
        <name>Provinces</name>
    </types>
    <types>
        <members>Vancouver</members>
        <members>Calgary</members>
        <members>Toronto</members>
        <members>Montreal</members>
        <name>Cities</name>
    </types>
    <version>43.0</version>
</Package>

Ожидаемый результат:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
    <types>
        <members>Calgary</members>
        <members>Montreal</members>
        <members>Toronto</members>
        <members>Vancouver</members>
        <name>Cities</name>
    </types>    
    <types>
        <members>Alberta</members>
        <members>Ontario</members>
        <members>Quebec</members>
        <name>Provinces</name>
    </types>
    <version>43.0</version>
</Package>

Я начал с того, что пытался отсортировать типы по имени, но, похоже, он ничего не сортирует для меня

XSL:

<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="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="Package">
        <xsl:copy>
            <xsl:apply-templates select="@*"/>
            <xsl:apply-templates select="types">
                <xsl:sort select="name"/>
            </xsl:apply-templates>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

Ответы [ 2 ]

0 голосов
/ 25 июня 2018
<xsl:output method="xml" indent="yes"/>
    <xsl:template match="Package">
        <xsl:copy copy-namespaces="yes">
            <xsl:for-each select="types">
                <xsl:sort select="." order="descending"/>
                <types>
                    <xsl:for-each select="members">
                        <xsl:sort order="ascending"/>
                        <members>
                            <xsl:value-of select="."/>
                        </members>
                    </xsl:for-each>
                    <name>
                        <xsl:value-of select="name"/>
                    </name>
                </types>
            </xsl:for-each>
            <xsl:apply-templates select="version"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="version">
        <xsl:copy>
        <xsl:apply-templates/>
        </xsl:copy>
    </xsl:template>
Check it
0 голосов
/ 25 июня 2018

Ваш скрипт не выполнен, потому что вы забыли о пространствах имен. Например. Соответствие шаблону Package относится к этому имени в пусто пространство имен, тогда как ваш элемент ввода Package в http://soap.sforce.com/2006/04/metadata пространстве имен.

Итак, правильный скрипт XSLT должен:

  • включить это пространство имен в тег stylesheet, указав префикс (например, m),
  • ссылаются на имена тегов, используя только этот префикс.

Ниже у вас есть рабочий скрипт:

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

  <xsl:template match="m:Package">
    <xsl:copy>
      <xsl:apply-templates select="@*"/>
      <xsl:apply-templates select="m:types">
        <xsl:sort select="m:name"/>
      </xsl:apply-templates>
      <xsl:apply-templates select="*[local-name() != 'types']"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="m:types">
    <xsl:copy>
      <xsl:apply-templates select="@*"/>
      <xsl:apply-templates select="m:members">
        <xsl:sort select="."/>
      </xsl:apply-templates>
      <xsl:apply-templates select="m:name"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="node()|@*">
    <xsl:copy><xsl:apply-templates select="node()|@*"/></xsl:copy>
  </xsl:template>
</xsl:stylesheet>

Как видите, я добавил шаблон, соответствующий types, чтобы обеспечить сортировать по members, как вы указали.

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