Подозрительно, если XML для каждого элемента api
будет изменен на следующее, результат будет отсортирован, как и ожидалось:
<api id="apiId">
<id>apiId</id>
<foos>
<foo />
</foo>
</api>
Кроме того, если a) XML для каждого элемента api
изменяется, чтобы полностью удалить атрибут id
<api>
<id>apiId</id>
<foos>
<foo />
</foo>
</api>
и b) только секунда ссылка на @id
в файле XSL изменяется на id
, результат все равно будет отсортирован в алфавитном порядке!
Возможно, XslCompiledTransform
пытается отсортировать дочерний элемент с именем id
вместо атрибута с именем id
, или это может быть просто глупой удачей. В любом случае, я убедился, что он готов правильно отсортировать дочерний элемент с именем id
.
Имея это в виду, я могу придумать два обходных пути, но оба требуют, чтобы вы имели некоторый уровень контроля над процессом преобразования.
Подход 1: Вы можете изменить XML
Измените процесс записи исходного XML, указав id
в качестве первого элемента, содержащегося в элементе api
. Затем обновите XSL, чтобы заменить ссылки на @id
на id
.
Подход 2: Вы можете предварительно обработать XML перед применением XSL
Используйте XSL-преобразование, чтобы переместить значение атрибута id
в дочерний элемент api
, затем примените тот же XSL, что и в Approach 1 , к промежуточному документу XML. Преобразование документа дважды было бы менее желательным при обработке больших файлов XML.
Следующий XSL выведет вас из исходного XML в промежуточный XML:
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.1">
<!-- recursively copy each element (including root) -->
<xsl:template match="*|/">
<xsl:copy>
<!-- xsl:copy ignores attributes, copy those as well -->
<xsl:copy-of select="@*"/>
<!-- continue to deep copy the element -->
<xsl:apply-templates />
</xsl:copy>
</xsl:template>
<!-- for api elements, move the id attribute into an element -->
<xsl:template match="api">
<api>
<id>
<xsl:value-of select="@id"/>
</id>
<!-- continue deep copy of api element contents -->
<xsl:apply-templates />
</api>
</xsl:template>
</xsl:stylesheet>
Надеюсь, это поможет!