XSLT从for-each之外的另一个变量访问元素的值

时间:2015-04-10 14:40:06

标签: xslt xslt-1.0

我的要求非常荒谬。我很抱歉! 我是这种令人讨厌的要求的受害者!

源XML:

<Order>
    <OrderLines>
        <orderline><!-- Items may be repeated but with different instructions -->
            <id>100</id>
            <quantity>1</quantity>
            <instruction>Instruction one</instruction>
        </orderline>
        <orderline>
            <id>100</id>
            <quantity>1</quantity>
            <instruction>Instruction two</instruction>
        </orderline>
        <orderline>
            <id>101</id>
            <quantity>2</quantity>
            <instruction>Some text</instruction>
        </orderline>
    </OrderLines>
</Order>

来源二(可以使用$ Order / PODetail访问)

<PODetails>
    <Intro>
        <seqno>001</seqno>
        <text>Sometext</text>
    </Intro>
    <item> <!--Items will not be repeated -->
        <seqno>002</seqno>
        <id>100</id>
        <name>COAL</name>
        <Supplier>123</Supplier>
    </item>
    <details>
        <seqno>003</seqno>
        <quantity>2</quantity>
        <unitprice>150</unitprice>
    </details>
    <item>
        <seqno>004</seqno>
        <id>101</id>
        <name>MICA</name>
        <Supplier>123</Supplier>
    </item>
    <details>
        <seqno>005</seqno>
        <quantity>2</quantity>
        <unitprice>160</unitprice>
    </details>
    <Summary>
        <seqno>006</seqno>
        <text>Sometext</text>
    </Summary>
</PODetails>

输出XML:

<PODetails>
    <Intro>
        <seqno>001</seqno>
        <text>Sometext</text>
    </Intro>
    <item>
        <seqno>002</seqno>
        <id>100</id>
        <name>COAL</name>
        <Supplier>123</Supplier>
        <instruction>Instruction one</instruction ><!--From source one-->
    </item>
    <details>
        <seqno>003</seqno>
        <quantity>1</quantity>
        <unitprice>150</unitprice>
    </details>
    <item>
        <seqno>004</seqno>
        <id>100</id>
        <name>COAL</name>
        <Supplier>123</Supplier>
        <instruction>Instruction two</instruction >
    </item>
    <details>
        <seqno>005</seqno>
        <quantity>1</quantity>
        <unitprice>150</unitprice>
    </details>
    <item>
        <seqno>006</seqno>
        <id>101</id>
        <name>MICA</name>
        <Supplier>123</Supplier>
        <instruction>some text<instruction>
    </item>
    <details>
        <seqno>007</seqno>
        <quantity>2</quantity>
        <unitprice>160</unitprice>
    </details>
    <Summary>
        <seqno>008</seqno>
        <text>Sometext</text>
    </Summary>
</PODetails>

解释

  1. 源1中的itemquantity优先(即使o / p采用源2的结构)。 原因: 源一中的项目将在源二中提供。不同之处在于,数量总计为源2中的特定数量。 在源二中查找项目100的数量总计为2。 源1的原因可能包含相同项目的不同instruction,因此必须单独处理。但是,其他详细信息如unitprice这些项目与源二中包含的相同。例如,项目煤有不同的指令,它们必须在输出中包含两次。但是,unitprice等其他详细信息与从源2获取的信息相同。

  2. seqno只是根元素的每个第一级兄弟的增量数字,introitemdetail,{{1} } ...

  3. 我面临的挑战是当我遍历源{1}的每个summary时访问源二的元素。
  4. 澄清 来到xslt时我是个菜鸟。但是,即使我已经完成所有的noobness,我推断<orderline> <item>应该包含<details>之类的内容,但我无法更改xsd,因为它与其他系统相关联。当我遍历每个<items>时,甚至可以访问 Source Two变量。通过一些初步研究here,我推断这是不可能的。有工作吗?

    提前致谢!

2 个答案:

答案 0 :(得分:1)

我仍然不理解您解释的部分内容。这一个:

  

不同之处在于数量是针对特定数量的总和   来源二的数量。 查找项目100的数量总计最多2英寸   来源二。

假设源文档中的每个item输出应该只有一个details(以及一个伴随orderline节点) - IOW,不需要对订单行进行分组通过他们的身份并总结他们的数量 - 我建议采用以下方法:

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:param name="lookup-doc" select="document('source2.xml')" />

<xsl:key name="item" match="item" use="id" />

<xsl:template match="/Order">
    <PODetails>
        <xsl:copy-of select="$lookup-doc/PODetails/Intro"/>
        <xsl:apply-templates select="OrderLines/orderline"/>
        <Summary>
            <seqno><xsl:value-of select="format-number(2 * count(OrderLines/orderline) + 2, '000')"/></seqno>
            <xsl:copy-of select="$lookup-doc/PODetails/Summary/text"/>
        </Summary>
    </PODetails>
</xsl:template>

<xsl:template match="orderline">
    <xsl:variable name="orderline" select="." />
    <xsl:variable name="id" select="id" />
    <xsl:variable name="number" select="2 * position()" />
    <!-- switch context to lookup document -->
    <xsl:for-each select="$lookup-doc">
        <xsl:variable name="item" select="key('item', $id)" />
        <item>
            <seqno><xsl:value-of select="format-number($number, '000')"/></seqno>
            <xsl:copy-of select="$id | $item/name | $item/Supplier | $orderline/instruction"/>
        </item>
        <details>
            <seqno><xsl:value-of select="format-number($number + 1, '000')"/></seqno>
            <xsl:copy-of select="$orderline/quantity"/>
            <xsl:copy-of select="$item/following-sibling::details[1]/unitprice"/>
        </details>
    </xsl:for-each>
</xsl:template> 

</xsl:stylesheet>

答案 1 :(得分:0)

根据以下假设:

  1. 您当前的节点是orderline,可以通过template match="orderline"for-each select="orderline"
  2. $ Order变量在范围内且可以XPath(您同时标记了XSLT 1.0和XSLT 2.0,所以我们肯定不知道)。
  3. 然后你会看到像这样的XPath来访问,比如unitprice

    <xsl:value-of
        select="$Order/PODetails/item[id = current()/id]
        /following-sibling::details[1]/unitprice"/>
    

    可能需要根据$ Order变量的性质进行调整。另外,我在飞行中键入了这个,所以没有测试我的错别字。