如何使用XSLT / XSL

时间:2016-08-02 01:25:49

标签: xml xslt transformation

我的应用程序收到一个文件,其中包含名为“si”的最低元素中的几个值,我需要在名为“ssi”的子元素中打破其中一些值,因为其他应用程序将只接受这种方式。并不是所有的“si”都会在“ssi”中被打破,只有一些根据内部规则。此外,输入文件中作为“ssi”出现的所有元素必须分组在“si 999”下。

在下面的xml中,“si”代表subitem,“ssi”代表sub-subitem,“sf”代表subfield。 “sf”仅出现在输出中,它是可能的最低元素。它发生在这里,因为某些代码实际上是一组子代码,输入文件不会尽可能地将它们分开,但是另一个应用程序会期望这样。

例如:

<c:si name="001" value="1234"/>

需要在

中进行转换
<c:si name="001">
 <c:ssi name="sf1" value="12"/>
 <c:ssi name="sf2" value="34"/>
<\c:si>

<c:si name="002" value="abcd"/>

将不会发生变化,因此输出将完全相同。换句话说,有一些内部业务规则说si 001实际上是两个子代码的连接,而si 002只是一个代码。内部输入未显示,输出必须根据以下示例清除。

所有输入ssi必须在si name =“999”

下移动

例如:

<c:ssi name="0001" value="123456"/>
<c:ssi name="0002" value="abcdef"/>

进入xml输出:

<c:si name="999">
 <c:ssi name="0001" value="123456"/>
 <c:ssi name="0002" value="abcdef"/>
</c:si>

这里是整个例子:

输入xml

<c:product xmlns:c="myapp">
       <c:item>
              <c:si name="001" value="1234"/>
              <c:ssi name="0001" value="123456"/>
              <c:si name="002" value="abcd"/>
              <c:ssi name="0002" value="abcdef"/>
       </c:item>
       <c:item>
              <c:si name="001" value="9876"/>
              <c:ssi name="0001" value="987654"/>
              <c:si name="002" value="ghij"/>
              <c:ssi name="0002" value="lmnopq"/>
       </c:item>
</c:product>

所需的输出文件:

<c:product xmlns:c="myapp">
       <c:item>
              <c:si name="001">
                 <c:ssi name="sf1" value="12"/>
                 <c:ssi name="sf2" value="34"/>
              <\c:si>

              <c:si name="002" value="abcd"/>

              <c:si name="999">
                 <c:ssi name="0001" value="123456"/>
                 <c:ssi name="0002" value="abcdef"/>
              <\c:si>
       </c:item>
       <c:item>
              <c:si name="001">
                 <c:ssi name="sf1" value="98"/>
                 <c:ssi name="sf2" value="76"/>
              <\c:si>

              <c:si name="002" value="ghij"/>

              <c:si name="999">
                 <c:ssi name="0001" value="987654"/>
                 <c:ssi name="0002" value="lmnopq"/>
              <\c:si>
       </c:item>
</c:product>

今天,我通过解析输入文件并使用一些临时变量来调整输出。最近,我了解了XSLT / XSL,并发现它在我的场景中有多么有用。如果它只是少数几个元素XSL已经非常有用,但因为它是一个非常好的数量,它变得更适合我的情况。你可以想象,当你认为我可以直到100 si并且直到1000 ssi时,你的努力有多大。

那么,如何将所有传入的ssi移动到si 999以及如何应用在“sf”中转换元素值的XSL?如果我可以为每次转换创建一个XSL文件/块,那么保存应用程序会更容易。

1 个答案:

答案 0 :(得分:0)

IIUC,你想做的事情如下:

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:c="myapp">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

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

<xsl:template match="c:item">
    <xsl:copy>
        <c:si name="001">
            <xsl:apply-templates select="c:si[@name='001']"/>
        </c:si>
        <xsl:apply-templates select="c:si[not(@name='001')]"/>
        <c:si name="999">
            <xsl:apply-templates select="c:ssi"/>
        </c:si>
    </xsl:copy>
</xsl:template>

<xsl:template match="c:si[@name='001']">
    <c:ssi name="sf1" value="{substring(@value, 1, 2)}"/>
    <c:ssi name="sf2" value="{substring(@value, 3, 2)}"/>
</xsl:template>

</xsl:stylesheet>

请注意,这会创建001和999子项,无论它们是否包含内容。