#xslt
#xslt
Вопрос:
в моем исходном XML-файле у меня есть элемент lines, содержащий N элементов line. Каждый элемент line имеет groupid и элемент lineNo. lineNo — это уникальное целочисленное значение.
У меня также есть элемент groups, содержащий M элементов group. Для каждого отдельного группового идентификатора из линейных элементов у меня есть ровно один групповой элемент, поэтому groupid уникален внутри групповых элементов.
Теперь я хочу преобразовать xml таким образом, чтобы добавить данные из элемента group в соответствующий элемент line, но только в элемент line с min. Отсутствует строка для этого идентификатора группы.
Можно ли это сделать с помощью XSLT 1.0? Смотрите примеры xml-файлов ниже.
большое вам спасибо и с наилучшими пожеланиями
Тобиас
Вот упрощенный ввод:
<test>
<lines>
<line>
<groupid>1</groupid>
<lineNo>1</lineNo>
</line>
<line>
<groupid>1</groupid>
<lineNo>2</lineNo>
</line>
<line>
<groupid>1</groupid>
<lineNo>3</lineNo>
</line>
<line>
<groupid>2</groupid>
<lineNo>4</lineNo>
</line>
<line>
<groupid>2</groupid>
<lineNo>5</lineNo>
</line>
</lines>
<groups>
<group>
<groupid>1</groupid>
<groupTotal>100</groupTotal>
</group>
<group>
<groupid>2</groupid>
<groupTotal>200</groupTotal>
</group>
</groups>
</test>
И вот ожидаемый результат.
<test2>
<lines>
<line>
<groupid>1</groupid>
<lineNo>1</lineNo>
<groupTotal>100</groupTotal>
</line>
<line>
<groupid>1</groupid>
<lineNo>2</lineNo>
<groupTotal/>
</line>
<line>
<groupid>1</groupid>
<lineNo>3</lineNo>
<groupTotal/>
</line>
<line>
<groupid>2</groupid>
<lineNo>4</lineNo>
<groupTotal>200</groupTotal>
</line>
<line>
<groupid>2</groupid>
<lineNo>5</lineNo>
<groupTotal/>
</line>
</lines>
</test2>
Ответ №1:
Вот один из способов взглянуть на это:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"/>
<xsl:key name="line-by-group" match="line" use="groupid" />
<xsl:template match="/">
<test2>
<lines>
<xsl:for-each select="test/groups/group">
<xsl:apply-templates select="key('line-by-group', groupid)">
<xsl:with-param name="total" select="groupTotal"/>
</xsl:apply-templates>
</xsl:for-each>
</lines>
</test2>
</xsl:template>
<xsl:template match="line">
<xsl:param name="total"/>
<xsl:copy>
<xsl:copy-of select="groupid | lineNo"/>
<xsl:if test="position()=1">
<groupTotal><xsl:value-of select="$total"/></groupTotal>
</xsl:if>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Вот еще одна (при условии, что строки отсортированы по группам):
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"/>
<xsl:key name="group" match="group" use="groupid" />
<xsl:template match="/">
<test2>
<lines>
<xsl:for-each select="test/lines/line">
<xsl:copy>
<xsl:copy-of select="groupid | lineNo"/>
<xsl:if test="not(groupid=preceding-sibling::line[1]/groupid)">
<groupTotal>
<xsl:value-of select="key('group', groupid)/groupTotal"/>
</groupTotal>
</xsl:if>
</xsl:copy>
</xsl:for-each>
</lines>
</test2>
</xsl:template>
</xsl:stylesheet>