我有一个带有物料清单的xml文件,必须将其转换为文本文件以进行进一步处理。 xml文件具有一种方法,如果在“行”节点中“数量” = 0并且“组件”为空,则应该将“父级”的值用于接下来的行,直到找到下一个“父级”行。在这些组件行中,必须跳过“父级”的值。
我正在用变量或参数来存储@Parent的值以进行进一步处理。我发现xslt不支持;-)
有人可以给我提示如何处理此xml文件吗?我可以使用什么方法?我已经阅读了很多带有参数和递归处理的命名模板,但是找不到适合我情况的正确方法。
我在for-each循环中进行了尝试,并能够将其存储在变量中。
示例非常简化的输入XML
<Page>
<Line>
<Quantity>0</Quantity>
<Component></Component>
<Parent>ParentID1</Parent>
</Line>
<Line>
<Quantity>4</Quantity>
<Component>ComponentID1</Component>
<Parent>YYY</Parent>
</Line>
<Line>
<Quantity>2</Quantity>
<Component>ComponentID2</Component>
<Parent>ZZZ</Parent>
</Line>
<Line>
<Quantity>0</Quantity>
<Component></Component>
<Parent>ParentID2</Parent>
</Line>
<Line>
<Quantity>3</Quantity>
<Component>ComponentID4</Component>
<Parent>AAA</Parent>
</Line>
<Line>
<Quantity>2</Quantity>
<Component>ComponentID5</Component>
<Parent>XXX</Parent>
</Line>
<Page>
例如xml的预期输出(可以丢弃标题)
#Parent~Component~Quantity
ParentID1~ComponentID1~4
ParentID1~ComponentID2~2
ParentID2~ComponentID4~3
ParentID2~ComponentID5~2
答案 0 :(得分:0)
如果我正确理解这一点,则可以这样做:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" encoding="UTF-8" />
<xsl:key name="cpmt" match="Line[Component/text()]" use="generate-id(preceding-sibling::Line[not(Component/text())][1])" />
<xsl:template match="/Page">
<xsl:for-each select="Line[not(Component/text())]">
<xsl:variable name="parent" select="Parent" />
<xsl:for-each select="key('cpmt', generate-id())">
<xsl:value-of select="$parent"/>
<xsl:text>-</xsl:text>
<xsl:value-of select="Component"/>
<xsl:text>-</xsl:text>
<xsl:value-of select="Quantity"/>
<xsl:text> </xsl:text>
</xsl:for-each>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
请注意,我省略了Quantity = 0
的要求;如果至关重要,则可以将其添加到谓词中。
如果您的处理器支持XSLT 2.0,那么使用xsl:for-each-group
可以更容易:
XSLT 2.0
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" encoding="UTF-8" />
<xsl:template match="/Page">
<xsl:for-each-group select="Line" group-starting-with="Line[not(Component/text())]">
<xsl:variable name="parent" select="Parent" />
<xsl:for-each select="current-group()[position() > 1]">
<xsl:value-of select="$parent, Component, Quantity" separator="-"/>
<xsl:text> </xsl:text>
</xsl:for-each>
</xsl:for-each-group>
</xsl:template>
</xsl:stylesheet>
答案 1 :(得分:0)
这是XSLT 2/3的替代方案:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="#all"
version="3.0">
<xsl:output method="text" />
<xsl:template match="Page">
<xsl:for-each-group select="Line" group-starting-with="Line[Quantity = 0 and not(normalize-space(Component))]">
<xsl:value-of select="tail(current-group())/string-join((current()/Parent, Component, Quantity), '~')" separator=" "/>
<xsl:text> </xsl:text>
</xsl:for-each-group>
</xsl:template>
</xsl:stylesheet>