Атрибуты списка XSLT в порядке их появления в XML-файле - PullRequest
1 голос
/ 15 апреля 2019

У меня есть большое количество XML-файлов со структурой, подобной следующей, хотя они намного больше:

<?xml version="1.0" encoding="UTF-8"?>
<a a1="3.0" a2="ABC">
  <b b1="P1" b2="123">first
  </b>
  <b b1="P2" b2="456" b3="xyz">second
  </b>
</a>

Я хочу получить следующий вывод:

1|1|b1
1|2|b2
2|1|b1
2|2|b2
2|3|b3

где:

  1. Поле 1 является порядковым номером для узлов / a / b
  2. Поле 2 - это порядковый номер атрибута в том виде, в каком он отображается в XML-файле
  3. Поле 3 - это имя атрибута (не значение)

Я не совсем знаю, как правильно рассчитать поле 2.

Я подготовил следующий файл xslt:

<?xml version="1.0"?>
<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="/">
  <xsl:for-each select="a/b/@*">
   <xsl:value-of select="count(../preceding-sibling::*)+1"/>
   <xsl:text>|</xsl:text>
   <!-- TODO: This is not correct -->
   <xsl:value-of select="count(preceding-sibling::*)+1"/>
   <xsl:text>|</xsl:text>
   <xsl:value-of select="name()"/>
   <xsl:text>&#10;</xsl:text>
  </xsl:for-each>
 </xsl:template>

</xsl:stylesheet>

но когда я запускаю следующую команду:

xsltproc a.xslt a.xml > a.csv

Я получаю неправильный вывод, так как поле 2 не представляет порядковый номер атрибута:

1|1|b1
1|1|b2
2|1|b1
2|1|b2
2|1|b3

Есть ли у вас какие-либо предложения о том, как получить правильный вывод, пожалуйста?

Обратите внимание, что ответы, предоставленные в XSLT для атрибутов заказа , не дают решения этой проблемы.

Порядок атрибутов не имеет значения в XML. Например, <a a1="3.0" a2="ABC"> и <a a1="3.0" a2="ABC"> эквивалентны.

Однако этот конкретный вопрос является частью более крупного приложения, в котором важно установить порядок, в котором атрибуты появляются в данных XML-файлах (а не в XML-файлах, которые эквивалентны им).

Ответы [ 2 ]

2 голосов
/ 15 апреля 2019

Хотя, как говорит kjhughes в комментариях, порядок атрибутов незначителен.Тем не менее, вы все равно можете выбрать их и использовать элемент position(), чтобы получить числа, за которыми вы хотите (Вы просто не можете быть уверены, что порядок их вывода будет соответствовать порядку их появления в XML, хотя обычно это будетслучай).

Попробуйте это XSLT.Обратите внимание на вложенное использование xsl:for-each, чтобы сначала выбрать только b элементов, чтобы получить их позицию, прежде чем получить атрибуты, которые затем имеют свою собственную отдельную позицию.

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output method="text" />

 <xsl:template match="/">
   <xsl:for-each select="a/b">
     <xsl:variable name="bPosition"  select="position()"/>
     <xsl:for-each select="@*"> 
       <xsl:value-of select="$bPosition"/>
       <xsl:text>|</xsl:text>
       <xsl:value-of select="position()"/>
       <xsl:text>|</xsl:text>
       <xsl:value-of select="name()"/>
       <xsl:text>&#10;</xsl:text>
    </xsl:for-each>
  </xsl:for-each>
 </xsl:template>
</xsl:stylesheet>
1 голос
/ 15 апреля 2019

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

<xsl:template match="/">
    <xsl:for-each select="a/b/@*">
        <xsl:value-of select="count(../preceding-sibling::*)+1"/>
        <xsl:text>|</xsl:text>
        <!-- TODO: This is not correct -->
        <xsl:value-of select="position() - 
               (if (count(../preceding-sibling::*)) then count(../preceding-sibling::*)+1 else 0)"/>
        <xsl:text>|</xsl:text>
        <xsl:value-of select="name()"/>
        <xsl:text>&#10;</xsl:text>
    </xsl:for-each>
</xsl:template>

Который производит следующий вывод:

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