通过XSLT递归实现多级物料清单

时间:2016-04-14 21:55:55

标签: xslt

我是XSLT的新手,我很难找到解决以下问题的方法。

我正在尝试从基于IPC-257x标准的XML文件输出项目的缩进物料清单(BOM)以及添加的序列ID。在源XML文件中,有一个<Item>元素,使用属性/值isTopLevel="Yes"定义。这个元素定义了整个BOM结构的顶级Item。 BOM结构的下一级是在此Item的<BillOfMaterial>子元素下定义的。每个子元素本身可以有自己的BOM结构,该结构在其<Item>祖先的兄弟之下定义。此外,这些子元素中的每一个都可能有自己的BOM结构,这些结构也是<Item>祖先的兄弟。

我尝试过(没有成功)许多不同的解决方案,首先将多个<xsl:for-each>语句嵌入到一起,然后才意识到这可能不是最佳实践。随后,我尝试定义多个<xsl:templates>;然而,这是难以理解的地方,主要是对同一节点使用多个模板以及需要使用<xsl:param>来定义过滤的想法。

我希望有人可以提供最佳实践建议或解决方案,而不是让自己更加困惑。我非常有信心递归迭代是必需的,但不知道如何到达那里。

提前感谢您的帮助!

XML Source(原版大得多的缩写版):     

<ProductDataeXchangePackage>
    <Items>
        <Item isTopLevel="No" itemIdentifier="0115020040" description="STL, SH 14GA CR">
            <BillOfMaterial>
                <BillOfMaterialItem billOfMaterialItemIdentifier="8151400002" itemQuantity=".0001" proprietarySequenceIdentifier="0" />
            </BillOfMaterial>
        </Item>
        <Item isTopLevel="No" itemIdentifier="3070001100" description="NUT, STD HEX M10-1.5 (SST)">
            <Attachments>
                <Attachment fileIdentifier="124559464" fileSize="52212"/>
                <Attachment fileIdentifier="124559465" fileSize="411068"/>
                <Attachment fileIdentifier="124559462" fileSize="32603"/>
            </Attachments>
        </Item>
        <Item isTopLevel="No" itemIdentifier="3070007006" description="WELDNUT, M6-1.0 (SST)"/>
        <Item isTopLevel="No" itemIdentifier="3070028000" description="WELDNUT, M5 X 0.8 (SST)"/>
        <Item isTopLevel="No" itemIdentifier="3070031000" description="WELDNUT, M12-1.75-6H (STEEL)"/>
        <Item isTopLevel="No" itemIdentifier="3110011100" description="WASHER, FLAT M10 SST (DIN125)"/>
        <Item isTopLevel="No" itemIdentifier="3110011120" description="WASHER, FLAT M12 SST (DIN125)"/>
        <Item isTopLevel="No" itemIdentifier="3150021100" description="LOCKWASHER, SPLIT M10 SST (DIN127)"/>
        <Item isTopLevel="No" itemIdentifier="3203271000" description="BOLT, CARRIAGE, M10-1.5 X 40MM"/>
        <Item isTopLevel="No" itemIdentifier="8151400002" description="SPEC, SHIPPING">
            <Attachments>
                <Attachment fileIdentifier="118969381" fileSize="399829"/>
            </Attachments>
        </Item>
        <Item isTopLevel="No" itemIdentifier="8172418068" description="SPEC,APPROVED ALT MATERIAL">
            <Attachments>
                <Attachment fileIdentifier="138337862" fileSize="145480"/>
                <Attachment fileIdentifier="138337863" fileSize="38243"/>
                <Attachment fileIdentifier="132421232" fileSize="35544"/>
            </Attachments>
        </Item>
        <Item isTopLevel="No" itemIdentifier="8398222254" description="SKID, 36.75 X 57">
            <Attachments>
                <Attachment fileIdentifier="130404636" fileSize="49406"/>
            </Attachments>
        </Item>
        <Item isTopLevel="No" itemIdentifier="8435567553" description="FAB INSTR., SIDE BRACE">
            <Attachments>
                <Attachment fileIdentifier="142071491" fileSize="102438"/>
                <Attachment fileIdentifier="142071490" fileSize="887808"/>
            </Attachments>
        </Item>
        <Item isTopLevel="No" itemIdentifier="8435567554" description="FAB INSTR., BASE">
            <Attachments>
                <Attachment fileIdentifier="172551083" fileSize="1881600"/>
                <Attachment fileIdentifier="172573685" fileSize="145681"/>
            </Attachments>
        </Item>
        <Item isTopLevel="No" itemIdentifier="8435567555" description="FAB INSTR., TOP">
            <Attachments>
                <Attachment fileIdentifier="171051100" fileSize="126563"/>
                <Attachment fileIdentifier="171051099" fileSize="1575424"/>
            </Attachments>
        </Item>
        <Item isTopLevel="No" itemIdentifier="8435602286" description="ASSY INST, RACK WELDMT, 37RU">
            <Attachments>
                <Attachment fileIdentifier="135543730" fileSize="155618"/>
            </Attachments>
        </Item>
        <Item isTopLevel="No" itemIdentifier="8435602287" description="FAB INST., CORNER POST, LEFT FRONT">
            <Attachments>
                <Attachment fileIdentifier="129272424" fileSize="603648"/>
                <Attachment fileIdentifier="132214666" fileSize="39296"/>
            </Attachments>
        </Item>
        <Item isTopLevel="No" itemIdentifier="8435602288" description="FAB INST., CORNER POST, RIGHT REAR">
            <Attachments>
                <Attachment fileIdentifier="121115929" fileSize="549888"/>
                <Attachment fileIdentifier="132214667" fileSize="37265"/>
            </Attachments>
        </Item>
        <Item isTopLevel="No" itemIdentifier="8435602289" description="FAB INST., CORNER POST, RIGHT FRONT">
            <Attachments>
                <Attachment fileIdentifier="129285018" fileSize="604160"/>
                <Attachment fileIdentifier="132214668" fileSize="38840"/>
            </Attachments>
        </Item>
        <Item isTopLevel="No" itemIdentifier="8435602290" description="FAB INST., CORNER POST, LEFT REAR">
            <Attachments>
                <Attachment fileIdentifier="132214669" fileSize="36957"/>
                <Attachment fileIdentifier="130362337" fileSize="702464"/>
            </Attachments>
        </Item>
        <Item isTopLevel="No" itemIdentifier="9435567553" description="BRACE, SIDE">
            <BillOfMaterial>
                <BillOfMaterialItem billOfMaterialItemIdentifier="8172418068" itemQuantity="0.0001" proprietarySequenceIdentifier="0"/>
                <BillOfMaterialItem billOfMaterialItemIdentifier="8435567553" itemQuantity="0.0001" proprietarySequenceIdentifier="0"/>
                <BillOfMaterialItem billOfMaterialItemIdentifier="0115020040" itemQuantity="11.00" proprietarySequenceIdentifier="1"/>
            </BillOfMaterial>
        </Item>
        <Item isTopLevel="No" itemIdentifier="9435567554" description="BASE, CABINET FRAME">
            <BillOfMaterial>
                <BillOfMaterialItem billOfMaterialItemIdentifier="8172418068" itemQuantity="0.0001" proprietarySequenceIdentifier="0"/>
                <BillOfMaterialItem billOfMaterialItemIdentifier="8435567554" itemQuantity="0.0001" proprietarySequenceIdentifier="0"/>
                <BillOfMaterialItem billOfMaterialItemIdentifier="0115020040" itemQuantity="50.7" proprietarySequenceIdentifier="1"/>
            </BillOfMaterial>
        </Item>
        <Item isTopLevel="No" itemIdentifier="9435567555" description="TOP, CABINET FRAME">
            <BillOfMaterial>
                <BillOfMaterialItem billOfMaterialItemIdentifier="8172418068" itemQuantity="0.0001" proprietarySequenceIdentifier="0"/>
                <BillOfMaterialItem billOfMaterialItemIdentifier="8435567555" itemQuantity="0.0001" proprietarySequenceIdentifier="0"/>
                <BillOfMaterialItem billOfMaterialItemIdentifier="0115020040" itemQuantity="50.7" proprietarySequenceIdentifier="1"/>
            </BillOfMaterial>
        </Item>
        <Item isTopLevel="Yes" itemIdentifier="9435602286" description="WELDMENT, 37RU RACK">
            <BillOfMaterial>
                <BillOfMaterialItem billOfMaterialItemIdentifier="3070001100" itemQuantity="2.000" proprietarySequenceIdentifier="0"/>
                <BillOfMaterialItem billOfMaterialItemIdentifier="3110011100" itemQuantity="2.000" proprietarySequenceIdentifier="0"/>
                <BillOfMaterialItem billOfMaterialItemIdentifier="3110011120" itemQuantity="2.000" proprietarySequenceIdentifier="0"/>
                <BillOfMaterialItem billOfMaterialItemIdentifier="3150021100" itemQuantity="2.000" proprietarySequenceIdentifier="0"/>
                <BillOfMaterialItem billOfMaterialItemIdentifier="3203271000" itemQuantity="2.000" proprietarySequenceIdentifier="0"/>
                <BillOfMaterialItem billOfMaterialItemIdentifier="8398222254" itemQuantity="1.0000" proprietarySequenceIdentifier="0"/>
                <BillOfMaterialItem billOfMaterialItemIdentifier="8435602286" itemQuantity="0.0001" proprietarySequenceIdentifier="0"/>
                <BillOfMaterialItem billOfMaterialItemIdentifier="9435567554" itemQuantity="1" proprietarySequenceIdentifier="1"/>
                <BillOfMaterialItem billOfMaterialItemIdentifier="9435567555" itemQuantity="1" proprietarySequenceIdentifier="2"/>
                <BillOfMaterialItem billOfMaterialItemIdentifier="9435602287" itemQuantity="1" proprietarySequenceIdentifier="3"/>
                <BillOfMaterialItem billOfMaterialItemIdentifier="9435602288" itemQuantity="1" proprietarySequenceIdentifier="4"/>
                <BillOfMaterialItem billOfMaterialItemIdentifier="9435602289" itemQuantity="1" proprietarySequenceIdentifier="5"/>
                <BillOfMaterialItem billOfMaterialItemIdentifier="9435602290" itemQuantity="1" proprietarySequenceIdentifier="6"/>
                <BillOfMaterialItem billOfMaterialItemIdentifier="9435567553" itemQuantity="4" proprietarySequenceIdentifier="8"/>
                <BillOfMaterialItem billOfMaterialItemIdentifier="3070031000" itemQuantity="8" proprietarySequenceIdentifier="9"/>
                <BillOfMaterialItem billOfMaterialItemIdentifier="3070007006" itemQuantity="8" proprietarySequenceIdentifier="10"/>
                <BillOfMaterialItem billOfMaterialItemIdentifier="3070028000" itemQuantity="2" proprietarySequenceIdentifier="11"/>
            </BillOfMaterial>
        </Item>
        <Item isTopLevel="No" itemIdentifier="9435602287" description="CORNER POST, LEFT FRONT">
            <BillOfMaterial>
                <BillOfMaterialItem billOfMaterialItemIdentifier="8172418068" itemQuantity="0.0001" proprietarySequenceIdentifier="0"/>
                <BillOfMaterialItem billOfMaterialItemIdentifier="8435602287" itemQuantity="0.0001" proprietarySequenceIdentifier="0"/>
                <BillOfMaterialItem billOfMaterialItemIdentifier="0115020040" itemQuantity="5.137" proprietarySequenceIdentifier="1"/>
            </BillOfMaterial>
        </Item>
        <Item isTopLevel="No" itemIdentifier="9435602288" description="CORNER POST, RIGHT REAR">
            <BillOfMaterial>
                <BillOfMaterialItem billOfMaterialItemIdentifier="8172418068" itemQuantity="0.0001" proprietarySequenceIdentifier="0"/>
                <BillOfMaterialItem billOfMaterialItemIdentifier="8435602288" itemQuantity="0.0001" proprietarySequenceIdentifier="0"/>
                <BillOfMaterialItem billOfMaterialItemIdentifier="0115020040" itemQuantity="5.137" proprietarySequenceIdentifier="1"/>
            </BillOfMaterial>
        </Item>
        <Item isTopLevel="No" itemIdentifier="9435602289" description="CORNER POST, RIGHT FRONT">
            <BillOfMaterial>
                <BillOfMaterialItem billOfMaterialItemIdentifier="8172418068" itemQuantity="0.0001" proprietarySequenceIdentifier="0"/>
                <BillOfMaterialItem billOfMaterialItemIdentifier="8435602289" itemQuantity="0.0001" proprietarySequenceIdentifier="0"/>
                <BillOfMaterialItem billOfMaterialItemIdentifier="0115020040" itemQuantity="5.137" proprietarySequenceIdentifier="1"/>
            </BillOfMaterial>
        </Item>
        <Item isTopLevel="No" itemIdentifier="9435602290" description="CORNER POST, LEFT REAR">
            <BillOfMaterial>
                <BillOfMaterialItem billOfMaterialItemIdentifier="8172418068" itemQuantity="0.0001" proprietarySequenceIdentifier="0"/>
                <BillOfMaterialItem billOfMaterialItemIdentifier="8435602290" itemQuantity="0.0001" proprietarySequenceIdentifier="0"/>
                <BillOfMaterialItem billOfMaterialItemIdentifier="0115020040" itemQuantity="5.137" proprietarySequenceIdentifier="1"/>
            </BillOfMaterial>
        </Item>
    </Items>
</ProductDataeXchangePackage>

这是对XSL的一次(非常粗略的)尝试;只进入一个BOM级别深度:

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

    <xsl:template match="ProductDataeXchangePackage/Items/Item[@isTopLevel='Yes']/BillOfMaterial">
        <xsl:for-each select="BillOfMaterialItem">
            <xsl:value-of select="position()"/>
            <xsl:text>&#09;</xsl:text>
            <xsl:value-of select="@billOfMaterialItemIdentifier"/>
            <xsl:text>&#10;</xsl:text>
            <!--<xsl:apply-templates/>-->
        </xsl:for-each>       
    </xsl:template>

    <!--
    <xsl:template name="test" match="item">
        <xsl:value-of select="@itemIdentifier"/>
        <xsl:for-each select="@itemIdentifier">
            <xsl:value-of select="@*"/>
            <xsl:text>&#10;</xsl:text>
        </xsl:for-each>
    </xsl:template>
    -->
</xsl:stylesheet>

这是所需的输出:

0   9435602286
1   3070001100
2   3110011100
3   3110011120
4   3150021100
5   3203271000
6   8398222254
7   8435602286
8   9435567554
9       8172418068
10      8435567554
11      0115020040
12          8151400002
13  9435567555
14      8172418068
15      8435567555
16      0115020040
17          8151400002
18  9435602287
19      8172418068
20      8435602287
21      0115020040
22          8151400002
23  9435602288
24      8172418068
25      8435602288
26      0115020040
27          8151400002
28  9435602289
29      8172418068
30      8435602289
31      0115020040
32          8151400002
33  9435602290
34      8172418068
35      8435602290
36      0115020040
37          8151400002
38  9435567553
39      8172418068
40      8435567553
41      0115020040
42          8151400002
43  3070031000
44  3070007006
45  3070028000

1 个答案:

答案 0 :(得分:1)

我不理解你输出的逻辑。我原本预计缩进会随着BOM层次结构的每个级别而增加 - 在给定的示例中看起来像这样:

9435602286
    3070001100
    3070007006
    3070028000
    3070031000
    3110011100
    3110011120
    3150021100
    3203271000
    8398222254
    8435602286
    9435567553
        0115020040
            8151400002
        8172418068
        8435567553
    9435567554
        0115020040
            8151400002
        8172418068
        8435567554
    9435567555
        0115020040
            8151400002
        8172418068
        8435567555
    9435602287
        0115020040
            8151400002
        8172418068
        8435602287
    9435602288
        0115020040
            8151400002
        8172418068
        8435602288
    9435602289
        0115020040
            8151400002
        8172418068
        8435602289
    9435602290
        0115020040
            8151400002
        8172418068
        8435602290

使用 key 可以轻松生成以递归方式将每个项目链接到其组件:

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

<xsl:key name="bom" match="Item" use="@itemIdentifier" />

<xsl:template match="/ProductDataeXchangePackage">
    <xsl:apply-templates select="Items/Item[@isTopLevel='Yes']"/>   
</xsl:template>

<xsl:template match="Item">
    <xsl:param name="indent"/>
    <xsl:value-of select="$indent"/>
    <xsl:value-of select="@itemIdentifier"/>
    <xsl:text>&#10;</xsl:text>
    <xsl:apply-templates select="key('bom', BillOfMaterial/BillOfMaterialItem/@billOfMaterialItemIdentifier)">
        <xsl:with-param name="indent" select="concat($indent, '&#9;')"/>
    </xsl:apply-templates>
</xsl:template>

</xsl:stylesheet>

加了:

  

然后如何通过proprietarySequenceIdentifier对输出进行排序   by itemIdentifier?

此请求的问题是proprietarySequenceIdentifier不是Item本身的属性;它是&#34;父母&#34;的BillOfMaterialItem孙子的一个属性。 Item

我把'#34;父母&#34;在引号中,因为它在源XML结构中并不是它的父级(这就是原始问题的内容)。

要解决此问题,我们必须Item&#34;回到&#34;并从相应的proprietarySequenceIdentifier节点获取BillOfMaterialItem值:

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

<xsl:key name="item" match="Item" use="@itemIdentifier" />
<xsl:key name="bom-item" match="BillOfMaterialItem" use="@billOfMaterialItemIdentifier" />

<xsl:template match="/ProductDataeXchangePackage">
    <xsl:apply-templates select="Items/Item[@isTopLevel='Yes']"> 
        <xsl:sort select="@itemIdentifier" data-type="number" order="ascending"/>
    </xsl:apply-templates>
</xsl:template>

<xsl:template match="Item">
    <xsl:param name="indent"/>
    <xsl:value-of select="$indent"/>
    <xsl:value-of select="@itemIdentifier"/>
    <xsl:text>&#10;</xsl:text>
    <xsl:apply-templates select="key('item', BillOfMaterial/BillOfMaterialItem/@billOfMaterialItemIdentifier)">
        <xsl:with-param name="indent" select="concat($indent, '&#9;')"/>
        <xsl:sort select="key('bom-item', @itemIdentifier)/@proprietarySequenceIdentifier" data-type="number" order="ascending"/>
        <xsl:sort select="@itemIdentifier" data-type="number" order="ascending"/>
    </xsl:apply-templates>
</xsl:template>

</xsl:stylesheet>