0

我需要通过添加一个新元素来转换 XML 文件,该元素的值基于当前文件中的数据和XML使用XSLT 1.0. 文件:

文件1:

<Table>
    <Row>
        <ColA>AValue1</ColA>
        <ColB>BValue1</ColB>
    </Row>
    <Row>
        <ColA>AValue2</ColA>
        <ColB>BValue2</ColB>
    </Row>
</Table>

文件2:

<Table>
    <Row>
        <ColA>AValue1</ColA>
        <ColB>BValue1</ColB>
        <ColC>CValue1</ColC>
    </Row>
    <Row>
        <ColA>AValue1</ColA>
        <ColB>BValue1</ColB>
        <ColC>CValue1</ColC>
    </Row>
<Row>
        <ColA>AValue1</ColA>
        <ColB>BValue1</ColB>
        <ColC>CValue2</ColC>
    </Row>
    <Row>
        <ColA>AValue1</ColA>
        <ColB>BValue1</ColB>
        <ColC>CValue3</ColC>
    </Row>
    <Row>
        <ColA>AValue2</ColA>
        <ColB>BValue2</ColB>
        <ColC>CValue1</ColC>
    </Row>
</Table>

文件3:

<Table>
    <Row>
        <ColC>CValue1</ColC>
        <ColD>ABC</ColD>
    </Row>
    <Row>
        <ColC>CValue2</ColC>
        <ColD>DEF</ColD>
    </Row>
    <Row>
        <ColC>CValue3</ColC>
        <ColD>DEF</ColD>
    </Row>
</Table>

File1 中的行通过 ColA 和 ColB 与 File2 中的行具有一对多的关系。

File2 中的行与 ColC 的 File3 中的行具有多对一关系。

对于 File1 中的每一行,我需要:

  1. 在 File2 中查找不同的 ColC 值以查找在 ColA 和 ColB 上匹配的行

  2. 对于每个不同的 ColC 值,在 File3 中查找 ColD 值以查找在 ColC 上匹配的行

  3. 计算在步骤 2 中查找的 ColD 值的出现次数。ColD 将具有两个值之一(例如“ABC”或“DEF”)。我需要知道“ABC”是否比“DEF”多,如果有,请将 <ColD>ABC</ColD> 添加到 File1 中的该行。否则将 <ColD>DEF</ColD> 添加到 File1 中的该行。最后,File1 中的每一行都应该有 <ColD>ABC</ColD> 或 <ColD>DEF</ColD>。

期望的结果(文件 1 转换):

<Table>
    <Row>
        <ColA>AValue1</ColA>
        <ColB>BValue1</ColB>
        <ColD>DEF</ColD>
    </Row>
    <Row>
        <ColA>AValue2</ColA>
        <ColB>BValue2</ColB>
        <ColD>ABC</ColD>
    </Row>
</Table>

<ColD>DEF</ColD> 将被添加到第一行,因为与 ABC 的 1 次(不同)出现相比,DEF 出现了两次。<ColD>ABC</ColD> 将被添加到第 2 行,因为出现了 ABC 和零 DEF。

4

2 回答 2

0

好吧,我会尝试一个建议,但我不确定是否能很好地理解所有内容,所以如果它没有意义,我会删除它。

我了解到您有一些相关的 Xml 文件模型。我的意思是您需要访问与 File1 中的元素相关的文件 2 中的元素,依此类推。我遇到了一些类似的情况,并通过应用第一个转换来解决所有文件中的所有引用(到处复制 XML 节点)并在这个“不相关的模型”上应用我更具体的转换来修复它。这更容易,但可能存在一些性能问题(如果有很多关系,则取消关联所有文件可能很长),在我的情况下,它是用于离线生成,因此不需要好的性能。

于 2012-10-31T17:28:12.813 回答
0

我想出了一个似乎可行的解决方案(尚未对其进行太多测试)。我在这里重新输入,所以要小心拼写错误。我最困难的事情是弄清楚如何选择独特的 ColC 值。再次查看解决方案,我不需要唯一值。我的想法是我会循环通过 $unique_c_values 来计算 ColD 值,但结果却不同。

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

<xsl:template match="Row">
    <xsl:copy>
        <xsl:apply-templates select="node()|@">

        <xsl:variable name="unique_c_values" select=
            "document('file2.xml')/Table/Row[current()/ColA = ColA and current()/ColB = ColB]/ColC[not(. = preceding-sibling::*/ColC[current()/ColA = ../ColA and current()/ColB = ../ColB])]"/>

        <xsl:variable name="d_values" select=
            "document('file3.xml')/Table/Row[ColC = $unique_c_values]/ColD"/>

        <xsl:choose>
            <xsl:when test="count($d_values[. = 'DEF']) &gt; count($d_values[. = 'ABC'])">
                <ColD>DEF</ColD>
            </xsl:when>
            <xsl:otherwise>
                <ColD>ABC</ColD>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:copy>
</xsl:template>
于 2012-11-06T21:03:44.690 回答