Xml XSLT根据childnode上的条件在输出中写入父级
我想根据一些条件输出一个xml 这是我的输入XMLXml XSLT根据childnode上的条件在输出中写入父级,xml,xslt,Xml,Xslt,我想根据一些条件输出一个xml 这是我的输入XML <YIORDER01> <IDOC> <E1ORHDR> <E1OROPR> <VORNR>0010</VORNR> <E1OROPR_MAT> <MATNR>M0003-01</MATNR&g
<YIORDER01>
<IDOC>
<E1ORHDR>
<E1OROPR>
<VORNR>0010</VORNR>
<E1OROPR_MAT>
<MATNR>M0003-01</MATNR>
<YE1OROPR_MAT>
<STTXT>REL</STTXT>
<MTART>ZPAR</MTART>
<POSTP>L</POSTP>
</YE1OROPR_MAT>
</E1OROPR_MAT>
<E1OROPR_MAT>
<MATNR>M0003-01</MATNR>
<YE1OROPR_MAT>
<STTXT>REL</STTXT>
<MTART>XYZ</MTART>
<POSTP>M</POSTP>
</YE1OROPR_MAT>
</E1OROPR_MAT>
</E1OROPR>
<E1OROPR>
<VORNR>0020</VORNR>
<E1OROPR_MAT>
<MATNR>M0003-01</MATNR>
<YE1OROPR_MAT>
<STTXT>REL</STTXT>
<MTART>ZPAR</MTART>
<POSTP>L</POSTP>
</YE1OROPR_MAT>
</E1OROPR_MAT>
</E1OROPR>
</E1ORHDR>
</IDOC>
</YIORDER01>
0010
M0003-01
雷尔
ZPAR
L
M0003-01
雷尔
XYZ
M
0020
M0003-01
雷尔
ZPAR
L
输出是这样的
<PartOrderList>
<PartOrder>
<OperationBONumber>0010</OperationBONumber>
<PartOrderLine>
<MaterialNumber>M0003-01</MaterialNumber>
<ShipmentType>REL</ShipmentType>
</PartOrderLine>
</PartOrder>
<PartOrder>
<OperationBONumber>0020</OperationBONumber>
</PartOrder>
</PartOrderList>
0010
M0003-01
雷尔
0020
我的XSLT是这样的
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="YIORDER01">
<xsl:element name="PartOrderList">
<xsl:for-each select="IDOC/E1ORHDR/E1OROPR">
<xsl:element name="PartOrder">
<xsl:element name="OperationBONumber">
<xsl:value-of select="VORNR"/>
</xsl:element>
<xsl:for-each select="E1OROPR_MAT">
<xsl:if test="YE1OROPR_MAT/MTART = 'ZPAR' and YE1OROPR_MAT/POSTP = 'L'">
<xsl:element name="PartOrderLine">
<xsl:element name="MaterialNumber">
<xsl:value-of select="MATNR"/>
</xsl:element>
<xsl:element name="ShipmentType">
<xsl:value-of select="YE1OROPR_MAT/STTXT"/>
</xsl:element>
</xsl:element>
</xsl:if>
</xsl:for-each>
</xsl:element>
</xsl:for-each>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
这里的问题是,我不想在输出中使用第二个“PartOrder”标记,因为它没有任何“PartOrderLine”子级
xslt中使用的规则:
有什么方法可以使用xslt实现这一点吗
请提供帮助。您需要将条件作为谓词添加到每个select表达式的外部
,以便只为您知道的每个over元素生成至少一个PartOrderLine
<xsl:for-each select="IDOC/E1ORHDR/E1OROPR[
E1OROPR_MAT/YE1OROPR_MAT[MTART = 'ZPAR' and POSTP = 'L']]">
仅供参考:以下是我的做法。这种方法的优点是:
- 您的有效行规则只定义一次,因此如果您更改逻辑,它将同时更改POs和POLINE
- 如果你想修改任何东西,每一条数据都很容易找到
- 所有模板都可以并行运行,(通常)在多处理器机器上运行得更快
。
有效的
无效的
也就是说,为了进一步改进这一点,可能还有很多工作要做/您选择的选项应该取决于您最适合使用的代码(在某种程度上;显然,任何新方法都有一个学习曲线,可能会导致最初的不适,因此这一点应该考虑到长期考虑).旁注:我会避免使用for-each循环;XSLT被设计成以功能的方式工作;因此,使用模板执行for-each而不是显式for-each循环更符合语言的预期用途(一旦您了解了这种方法,您将获得更好的性能并使事情更易于维护。注意:您的示例数据中还包含一个额外的r,这可能会导致它看起来像是工作代码有缺陷-ZPAR
r
是的,John,感谢您指出这一点。我已经编辑了这个问题。
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" indent="yes"/>
<!-- Part Order List -->
<xsl:template match="/*">
<xsl:element name="PartOrderList">
<xsl:apply-templates select=".//E1OROPR" />
</xsl:element>
</xsl:template>
<!-- Part Order List > Part Order -->
<xsl:template match="//E1OROPR">
<xsl:variable name="IsValid">
<xsl:call-template name="HasOrIsValidPOLine" />
</xsl:variable>
<xsl:if test="$IsValid='VALID'"> <!-- only display the part order if there's a valid line under it-->
<xsl:element name="PartOrder">
<xsl:apply-templates select=".//VORNR" />
<xsl:apply-templates select=".//E1OROPR_MAT" />
</xsl:element>
</xsl:if>
</xsl:template>
<!-- Part Order List > Part Order > Operational BO Number -->
<xsl:template match="//VORNR">
<xsl:element name="OperationBONumber">
<xsl:value-of select="text()"/>
</xsl:element>
</xsl:template>
<!-- Part Order List > Part Order > Part Order Line -->
<xsl:template match="//E1OROPR_MAT">
<xsl:variable name="IsValid">
<xsl:call-template name="HasOrIsValidPOLine" />
</xsl:variable>
<xsl:if test="$IsValid='VALID'">
<!-- only display the part order line if it's valid-->
<xsl:element name="PartOrderLine">
<xsl:apply-templates select=".//MATNR" />
<xsl:apply-templates select=".//STTXT" />
</xsl:element>
</xsl:if>
</xsl:template>
<!-- Part Order List > Part Order > Part Order Line > Material Number -->
<xsl:template match="//MATNR">
<xsl:element name="MaterialNumber">
<xsl:value-of select="text()"/>
</xsl:element>
</xsl:template>
<!-- Part Order List > Part Order > Part Order Line > Shipment Type -->
<xsl:template match="//STTXT">
<xsl:element name="ShipmentType">
<xsl:value-of select="text()"/>
</xsl:element>
</xsl:template>
<xsl:template name="HasOrIsValidPOLine">
<xsl:choose>
<xsl:when test=".//MTART/text() = 'ZPAR' and .//POSTP/text() = 'L'">VALID</xsl:when>
<xsl:otherwise>INVALID</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>