带有动态过滤器的 XSLT for-each 循环

XSLT for-each loops with dynamic filters

这是 XML-Message (SAP-IDOC) 的简化版本,我需要将其转换为更易于阅读的 XML,如下例所示。

这是一个 SAP Delivery IDOC,它为我提供了货物及其位置的信息。问题是,位置 10 和 20 可能在同一个纸箱 (E1EDL37) 中,并且具有与位置 3 不同的跟踪编号 (Field TRACKN)。

<DELVRY07>
<IDOC>
    <E1EDL20> <!-- Contains all positions-->
        <E1EDL24> <!--one Node for each position -->
            <POSNR>000010</POSNR>
            <MATNR>123</MATNR>
            <E1EDL41>
                <BSTNR>Fall 1</BSTNR>
            </E1EDL41>
        </E1EDL24>
        <E1EDL24><!--one Node for each position -->
            <POSNR>000020</POSNR>
            <MATNR>456</MATNR>
            <E1EDL41>
                <BSTNR>Fall 2</BSTNR>
            </E1EDL41>
        </E1EDL24>
        <E1EDL24><!--one Node for each position -->
            <POSNR>000030</POSNR>
            <MATNR>789</MATNR>
            <E1EDL41>
                <BSTNR>Fall 3</BSTNR>
            </E1EDL41>
        </E1EDL24>
        <E1EDL37><!--one Node for every carton-->
            <E1EDL49>
                <XSITD>UPS1</XSITD>
                <TRACKN>Track 1</TRACKN>
            </E1EDL49>
            <E1EDL44><!-- every position in the carton-->
                <VBELN>123456</VBELN>
                <POSNR>000010</POSNR>
            </E1EDL44>
            <E1EDL44><!-- every position in the carton-->
                <VBELN>456789</VBELN>
                <POSNR>000020</POSNR>
            </E1EDL44>
        </E1EDL37>
        <E1EDL37><!--one Node for every carton-->
            <E1EDL49>
                <XSITD>DPD</XSITD>
                <TRACKN>Track 2</TRACKN>
            </E1EDL49>
            <E1EDL44><!-- every position in the carton-->
                <VBELN>123456</VBELN>
                <POSNR>000030</POSNR>
            </E1EDL44>
        </E1EDL37>
    </E1EDL20>
</IDOC>
</DELVRY07>

这应该是xslt转换后的xml消息(或类似的消息):

<Shipment>
    <Positions>
        <POSNR>000010</POSNR>
        <MATNR>123</MATNR>
        <BSTNR>Fall 1</BSTNR>
        <TRACKN>Track 1</TRACKN>
        <XSITD>UPS1</XSITD>
    </Positions>
    <Positions>
        <POSNR>000020</POSNR>
        <MATNR>456</MATNR>
        <BSTNR>Fall 2</BSTNR>
        <TRACKN>Track 1</TRACKN>
        <XSITD>UPS1</XSITD>
    </Positions>
    <Positions>
        <POSNR>000030</POSNR>
        <MATNR>123</MATNR>
        <BSTNR>Fall 3</BSTNR>
        <TRACKN>Track 2</TRACKN>
        <XSITD>DPD</XSITD>
    </Positions>
</Shipment>

我试着用循环遍历 E1EDL24 元素并将信息写入变量。但从那时起,我将需要对所有 E1EDL44 进行循环并获取上面 E1EDL49 元素的 TRACKN 字段的值。

你能帮我想办法吗?

非常感谢您的帮助!

如果我正确地遵循了这一点(这完全不确定),您想为每个 "position" 创建一个记录并从匹配的 "carton":

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:strip-space elements="*"/>

<xsl:key name="carton-by-position" match="E1EDL37" use="E1EDL44/POSNR" />

<xsl:template match="/DELVRY07">
    <Shipment>
        <xsl:for-each select="IDOC/E1EDL20/E1EDL24">
            <Positions>
                <xsl:copy-of select="POSNR | MATNR | E1EDL41/BSTNR"/>
                <xsl:copy-of select="key('carton-by-position', POSNR)/E1EDL49/*"/>
            </Positions>
        </xsl:for-each>
    </Shipment>
</xsl:template>

</xsl:stylesheet>

试试这个模板:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="1.0">

  <xsl:output method="xml" indent="yes"/>

  <xsl:template match="/IDOC/E1EDL20">
    <xsl:variable name="parent" select="."/>
    <Shipment>
      <xsl:for-each select="E1EDL24/POSNR">
        <xsl:variable name="posnr" select="."/>
        <Position>
          <POSNR><xsl:value-of select="$posnr"/></POSNR>
          <MATNR><xsl:value-of select="../MATNR"/></MATNR>
          <BSTNR><xsl:value-of select="../E1EDL41/BSTNR"/></BSTNR>
          <TRACKN><xsl:value-of select="$parent/E1EDL37[E1EDL44/POSNR=$posnr]/E1EDL49/TRACKN"/></TRACKN>
          <XSITD><xsl:value-of select="$parent/E1EDL37[E1EDL44/POSNR=$posnr]/E1EDL49/XSITD"/></XSITD>
        </Position>
      </xsl:for-each>
    </Shipment>
    </xsl:template>

</xsl:stylesheet>

Online-Fiddle here