循环每个xml行的转换文件

时间:2013-02-21 09:22:16

标签: xml xslt

很明显,我对XML和XSLT的了解相当有限。请有人帮我一个翻译文件,该文件允许传递以下XML中的每个ItemNumber / Sales Order,以便为每个项目生成第二个XML。换句话说,我需要生成多个输出xmls(每个销售订单一个)。目前我只为初始xml上的最后一个订单项/销售订单获得一个输出xml。

这是我需要翻译的xml:

<?xml version="1.0" encoding="Windows-1252"?>
<postsalesorderssct Language='05' Language2='EN' CssStyle='' DecFormat='1' DateFormat='01' Role='01' Version='6.1.009' OperatorPrimaryRole='   '>
    <Item>
        <Key>
            <SalesOrder>197588</SalesOrder>
            <SourceWarehouse>A3</SourceWarehouse>
            <TargetWarehouse>PV</TargetWarehouse>
            <CustomerPoNumber/>
        </Key>
        <ItemNumber>000001</ItemNumber>
    </Item>
    <Item>
        <Key>
            <SalesOrder>197589</SalesOrder>
            <SourceWarehouse>A3</SourceWarehouse>
            <TargetWarehouse>HI</TargetWarehouse>
            <CustomerPoNumber/>
        </Key>
        <ItemNumber>000002</ItemNumber>
    </Item>
    <Item>
        <Key>
            <SalesOrder>197590</SalesOrder>
            <SourceWarehouse>A3</SourceWarehouse>
            <TargetWarehouse>WS</TargetWarehouse>
            <CustomerPoNumber/>
        </Key>
        <ItemNumber>000003</ItemNumber>
    </Item>
    <Item>
        <Key>
            <SalesOrder>197591</SalesOrder>
            <SourceWarehouse>A4</SourceWarehouse>
            <TargetWarehouse>HI</TargetWarehouse>
            <CustomerPoNumber/>
        </Key>
        <ItemNumber>000004</ItemNumber>
    </Item>
    <Item>
        <Key>
            <SalesOrder>197592</SalesOrder>
            <SourceWarehouse>A4</SourceWarehouse>
            <TargetWarehouse>PV</TargetWarehouse>
            <CustomerPoNumber/>
        </Key>
        <ItemNumber>000005</ItemNumber>
    </Item>
    <Item>
        <Key>
            <SalesOrder>197593</SalesOrder>
            <SourceWarehouse>A4</SourceWarehouse>
            <TargetWarehouse>WS</TargetWarehouse>
            <CustomerPoNumber/>
        </Key>
        <ItemNumber>000006</ItemNumber>
    </Item>
    <StatusOfItems>
        <ItemsProcessed>000006</ItemsProcessed>
        <ItemsInvalid>000000</ItemsInvalid>
    </StatusOfItems>
</postsalesorderssct>

以下是我目前使用的翻译文件:

    <?xml version="1.0" ?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" encoding="Windows-1252" omit-xml-declaration="yes" />
<xsl:template match="/">
<Query>
 <Key>
  <xsl:for-each select = "postsalesorderssct/Item/Key">
       <SalesOrder><xsl:value-of select="SalesOrder"/></SalesOrder>
  </xsl:for-each>
 </Key>
</Query>
</xsl:template>
</xsl:stylesheet>

以下是初始xml上每个ItemNumbers的必需输出。换句话说,我需要为每个销售订单编号生成其中一个:

<Query xmlns:xsd="http://www.w3.org/2001/XMLSchema-instance" xsd:noNamespaceSchemaLocation="SORQRY.XSD">
    <Key>
        <SalesOrder>197588</SalesOrder>
        <Invoice/>
    </Key>
    <Option>
        <IncludeStockedLines>Y</IncludeStockedLines>
        <IncludeNonStockedLines>Y</IncludeNonStockedLines>
        <IncludeFreightLines>Y</IncludeFreightLines>
        <IncludeMiscLines>Y</IncludeMiscLines>
        <IncludeCommentLines>Y</IncludeCommentLines>
        <IncludeCompletedLines>Y</IncludeCompletedLines>
        <IncludeSerials>N</IncludeSerials>
        <IncludeLots>Y</IncludeLots>
        <IncludeBins>Y</IncludeBins>
        <IncludeAttachedItems>N</IncludeAttachedItems>
        <IncludeCustomForms>Y</IncludeCustomForms>
        <IncludeDetailLineCustomForms>Y</IncludeDetailLineCustomForms>
        <XslStylesheet/>
    </Option>
</Query>

在期待中感谢你。

2 个答案:

答案 0 :(得分:1)

如果您可以使用XSLT 2.0,则以下内容应该有效......

XML输入

<postsalesorderssct Language='05' Language2='EN' CssStyle='' DecFormat='1' DateFormat='01' Role='01' Version='6.1.009' OperatorPrimaryRole='   '>
    <Item>
        <Key>
            <SalesOrder>197588</SalesOrder>
            <SourceWarehouse>A3</SourceWarehouse>
            <TargetWarehouse>PV</TargetWarehouse>
            <CustomerPoNumber/>
        </Key>
        <ItemNumber>000001</ItemNumber>
    </Item>
    <Item>
        <Key>
            <SalesOrder>197589</SalesOrder>
            <SourceWarehouse>A3</SourceWarehouse>
            <TargetWarehouse>HI</TargetWarehouse>
            <CustomerPoNumber/>
        </Key>
        <ItemNumber>000002</ItemNumber>
    </Item>
    <Item>
        <Key>
            <SalesOrder>197590</SalesOrder>
            <SourceWarehouse>A3</SourceWarehouse>
            <TargetWarehouse>WS</TargetWarehouse>
            <CustomerPoNumber/>
        </Key>
        <ItemNumber>000003</ItemNumber>
    </Item>
    <Item>
        <Key>
            <SalesOrder>197591</SalesOrder>
            <SourceWarehouse>A4</SourceWarehouse>
            <TargetWarehouse>HI</TargetWarehouse>
            <CustomerPoNumber/>
        </Key>
        <ItemNumber>000004</ItemNumber>
    </Item>
    <Item>
        <Key>
            <SalesOrder>197592</SalesOrder>
            <SourceWarehouse>A4</SourceWarehouse>
            <TargetWarehouse>PV</TargetWarehouse>
            <CustomerPoNumber/>
        </Key>
        <ItemNumber>000005</ItemNumber>
    </Item>
    <Item>
        <Key>
            <SalesOrder>197593</SalesOrder>
            <SourceWarehouse>A4</SourceWarehouse>
            <TargetWarehouse>WS</TargetWarehouse>
            <CustomerPoNumber/>
        </Key>
        <ItemNumber>000006</ItemNumber>
    </Item>
    <StatusOfItems>
        <ItemsProcessed>000006</ItemsProcessed>
        <ItemsInvalid>000000</ItemsInvalid>
    </StatusOfItems>
</postsalesorderssct>

XSLT 2.0

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output indent="yes"/>
    <xsl:strip-space elements="*"/>

    <xsl:template match="/postsalesorderssct/Item">
        <xsl:result-document href="{Key/SalesOrder}.xml">
            <Query xmlns:xsd="http://www.w3.org/2001/XMLSchema-instance" xsd:noNamespaceSchemaLocation="SORQRY.XSD">
                <Key>
                    <xsl:copy-of select="Key/SalesOrder"/>
                    <Invoice/>
                </Key>
                <Option>
                    <IncludeStockedLines>Y</IncludeStockedLines>
                    <IncludeNonStockedLines>Y</IncludeNonStockedLines>
                    <IncludeFreightLines>Y</IncludeFreightLines>
                    <IncludeMiscLines>Y</IncludeMiscLines>
                    <IncludeCommentLines>Y</IncludeCommentLines>
                    <IncludeCompletedLines>Y</IncludeCompletedLines>
                    <IncludeSerials>N</IncludeSerials>
                    <IncludeLots>Y</IncludeLots>
                    <IncludeBins>Y</IncludeBins>
                    <IncludeAttachedItems>N</IncludeAttachedItems>
                    <IncludeCustomForms>Y</IncludeCustomForms>
                    <IncludeDetailLineCustomForms>Y</IncludeDetailLineCustomForms>
                    <XslStylesheet/>
                </Option>
            </Query>        
        </xsl:result-document>      
    </xsl:template>

</xsl:stylesheet>

这将为您提供每个Item的单独文件。该文件的名称为SalesOrder

几个例子......

<强> 197588.xml

<Query xmlns:xsd="http://www.w3.org/2001/XMLSchema-instance"
       xsd:noNamespaceSchemaLocation="SORQRY.XSD">
   <Key>
      <SalesOrder>197588</SalesOrder>
      <Invoice/>
   </Key>
   <Option>
      <IncludeStockedLines>Y</IncludeStockedLines>
      <IncludeNonStockedLines>Y</IncludeNonStockedLines>
      <IncludeFreightLines>Y</IncludeFreightLines>
      <IncludeMiscLines>Y</IncludeMiscLines>
      <IncludeCommentLines>Y</IncludeCommentLines>
      <IncludeCompletedLines>Y</IncludeCompletedLines>
      <IncludeSerials>N</IncludeSerials>
      <IncludeLots>Y</IncludeLots>
      <IncludeBins>Y</IncludeBins>
      <IncludeAttachedItems>N</IncludeAttachedItems>
      <IncludeCustomForms>Y</IncludeCustomForms>
      <IncludeDetailLineCustomForms>Y</IncludeDetailLineCustomForms>
      <XslStylesheet/>
   </Option>
</Query>

<强> 197592.xml

<Query xmlns:xsd="http://www.w3.org/2001/XMLSchema-instance"
       xsd:noNamespaceSchemaLocation="SORQRY.XSD">
   <Key>
      <SalesOrder>197592</SalesOrder>
      <Invoice/>
   </Key>
   <Option>
      <IncludeStockedLines>Y</IncludeStockedLines>
      <IncludeNonStockedLines>Y</IncludeNonStockedLines>
      <IncludeFreightLines>Y</IncludeFreightLines>
      <IncludeMiscLines>Y</IncludeMiscLines>
      <IncludeCommentLines>Y</IncludeCommentLines>
      <IncludeCompletedLines>Y</IncludeCompletedLines>
      <IncludeSerials>N</IncludeSerials>
      <IncludeLots>Y</IncludeLots>
      <IncludeBins>Y</IncludeBins>
      <IncludeAttachedItems>N</IncludeAttachedItems>
      <IncludeCustomForms>Y</IncludeCustomForms>
      <IncludeDetailLineCustomForms>Y</IncludeDetailLineCustomForms>
      <XslStylesheet/>
   </Option>
</Query>

答案 1 :(得分:1)

正如丹尼尔所展示的那样,使用XSLT 2.0实现这一目标非常简单。不幸的是,对于纯XSLT 1.0,据我所知,这是不可能的,但如果你愿意更努力地工作,你可以达到同样的效果。

(我不会以任何方式称之为优雅解决方案,但这是我在没有XSLT 2.0的情况下解决此问题的第一种方法。)

我不知道您使用的是哪个XSLT处理器,因此我将使用xsltproc进行演示。

您可以先使用这样的样式表来创建一个包含所有<Query>元素的XML文件(使用xsltproc allQuery.xsl input.xml调用它):

    <!-- allQuery.xsl -->

    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
      xmlns:xsd="http://www.w3.org/2001/XMLSchema-instance">
      <xsl:output method="xml" encoding="Windows-1252" omit-xml-declaration="yes" indent="yes"/>

      <xsl:template match="/">
        <Queries>
            <xsl:apply-templates select="postsalesorderssct/Item/Key/SalesOrder"/>
        </Queries>
      </xsl:template>

      <xsl:template match="SalesOrder">
        <xsl:variable name="id" select="."/>
          <Query xsd:noNamespaceSchemaLocation="SORQRY.XSD">
            <Key>
              <xsl:copy>
                <xsl:apply-templates/>
              </xsl:copy>
              <Invoice/>
            </Key>
            <Option>
                <IncludeStockedLines>Y</IncludeStockedLines>
                <IncludeNonStockedLines>Y</IncludeNonStockedLines>
                <IncludeFreightLines>Y</IncludeFreightLines>
                <IncludeMiscLines>Y</IncludeMiscLines>
                <IncludeCommentLines>Y</IncludeCommentLines>
                <IncludeCompletedLines>Y</IncludeCompletedLines>
                <IncludeSerials>N</IncludeSerials>
                <IncludeLots>Y</IncludeLots>
                <IncludeBins>Y</IncludeBins>
                <IncludeAttachedItems>N</IncludeAttachedItems>
                <IncludeCustomForms>Y</IncludeCustomForms>
                <IncludeDetailLineCustomForms>Y</IncludeDetailLineCustomForms>
                <XslStylesheet/>
            </Option>
          </Query>
      </xsl:template>
    </xsl:stylesheet>

然后你可以有另一个简单的样式表:

<!-- extractQuery.xsl -->

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
  xmlns:xsd="http://www.w3.org/2001/XMLSchema-instance">

  <xsl:output method="xml" encoding="Windows-1252" omit-xml-declaration="yes" indent="yes"/>

  <!-- The sales order number you pass in on the command line. -->
  <xsl:param name="salesOrderNo"/>

  <xsl:template match="/">
    <!--
    Only apply the <Query> element with a <SalesOrder> descendant that has 
    $salesOrderNo as its text content -- in the case of this example, 197593.
    --> 
    <xsl:apply-templates select="Queries/Query[descendant::SalesOrder[. = $salesOrderNo]]"/>
  </xsl:template>

  <!-- Identity template -->
  <xsl:template match="node() | @*">
    <xsl:copy>
      <xsl:apply-templates select="@* | node()"/>
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

您可以将此样式表与此xsltproc一起使用,将要获取的<Query>元素的SalesOrder编号作为参数传递到样式表:

xsltproc --stringparam salesOrderNo 197593 extractQuery.xsl output.xml

这将产生以下输出:

<Query xmlns:xsd="http://www.w3.org/2001/XMLSchema-instance" xsd:noNamespaceSchemaLocation="SORQRY.XSD">
  <Key>
    <SalesOrder>197593</SalesOrder>
    <Invoice/>
  </Key>
  <Option>
    <IncludeStockedLines>Y</IncludeStockedLines>
    <IncludeNonStockedLines>Y</IncludeNonStockedLines>
    <IncludeFreightLines>Y</IncludeFreightLines>
    <IncludeMiscLines>Y</IncludeMiscLines>
    <IncludeCommentLines>Y</IncludeCommentLines>
    <IncludeCompletedLines>Y</IncludeCompletedLines>
    <IncludeSerials>N</IncludeSerials>
    <IncludeLots>Y</IncludeLots>
    <IncludeBins>Y</IncludeBins>
    <IncludeAttachedItems>N</IncludeAttachedItems>
    <IncludeCustomForms>Y</IncludeCustomForms>
    <IncludeDetailLineCustomForms>Y</IncludeDetailLineCustomForms>
    <XslStylesheet/>
  </Option>
</Query>

然后,您需要为要为其创建XML文件的每个销售订单号调用xsltproc一次。一种方法是创建另一个 XSLT样式表:

<!-- getSalesOrderNos.xsl -->

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
  xmlns:xsd="http://www.w3.org/2001/XMLSchema-instance">

  <xsl:output method="text" encoding="Windows-1252" omit-xml-declaration="yes"/>

  <xsl:template match="/">
    <xsl:apply-templates select="Queries/Query/Key/SalesOrder"/>
  </xsl:template>

  <xsl:template match="SalesOrder">
    <xsl:value-of select="."/><xsl:text>
</xsl:text>
  </xsl:template>

</xsl:stylesheet>

这将打印出所有销售订单编号的换行符分隔列表。然后,您可以将其与Bash脚本一起使用,如下所示:

xsltproc getSalesOrderNos.xsl output.xml | xargs -L1 -I no xsltproc \
-o SalesOrder-no.xml --stringparam salesOrderNo no extractQuery.xsl output.xml

从本质上讲,这将打印出output.xml中所有销售订单编号的列表,并为每个编号运行extractQuery.xsl一次 - 将参考号作为参数传递给{{1} - 并为每次转换的结果创建一个新文件(称为extractQuery.xsl)。如:

SalesOrder-<ordernumber>.xml

正如我所说,无论如何都不是很好。根据您可以访问的工具,您可以稍微简化此过程(例如,使用除XSLT之外的其他内容来提取销售订单编号列表并从那里继续)。