【问题标题】:Concatenate using XSLT v1.0 in XML to XML transformation在 XML 到 XML 的转换中使用 XSLT v1.0 进行连接
【发布时间】:2019-02-04 19:36:19
【问题描述】:

我正在做一个 XSLT 样式表来从 XML 转换为 XML,布局非常不同,我的情况令人头疼。我只能使用 XSLT 1.0,但我没有找到方法。

输入文件

<?xml version="1.0"?>
<Root>
  <ParentNode>
    <Node>
      <Id>1</Id>
      <Date>2019-02-01</Date>
      <ReferenceLine>1</ReferenceLine>
    </Node>
    <Node>
      <Id>2</Id>
      <Date>2019-02-01</Date>
      <ReferenceLine>1</ReferenceLine>
    </Node>
    <Node>
      <Id>3</Id>
      <Date>2019-02-02</Date>
      <ReferenceLine>2</ReferenceLine>
    </Node>
  </ParentNode>
</Root>

输出文件

<Lines>
  <Line>
    <LineNum>1</LineNum>
    <Node>1 - 2</Node>
  </Line>
 <Line>
    <LineNum>2</LineNum>
    <Node>3</Node>
 </Line>
</Lines>

所以我需要在输出中连接所有参考该行出现的节点。虽然我可以在输入文件中出现多个节点,但在输出文件中我只能在 Line 节点中出现一次。

【问题讨论】:

  • 您尝试过任何 XSLT 转换吗?你能告诉我们你的尝试吗?

标签: xml xslt xslt-1.0 cxml


【解决方案1】:

您可以使用 XSLT-1.0 方法Muenchian Grouping 来实现。如果你在 SO 上搜索,你会发现很多例子。应用此方法,您的样式表可能如下所示。

此样式表连接所有由- 分隔的Id

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:key name="nd" match="Node" use="ReferenceLine" />   

<xsl:template match="/Root/ParentNode">
    <Lines>
        <xsl:for-each select="Node[generate-id() = generate-id(key('nd',ReferenceLine)[1])]">
            <Line>
                <LineNum><xsl:value-of select="Id" /></LineNum>
                <Node>
                    <xsl:for-each select="key('nd',ReferenceLine)">
                        <xsl:sort order="ascending" select="Id" />
                        <xsl:value-of select="Id" />
                        <xsl:if test="position() != last()">
                            <xsl:text> - </xsl:text>
                        </xsl:if>
                    </xsl:for-each>
                </Node>
            </Line>
        </xsl:for-each>
    </Lines>
</xsl:template>

</xsl:stylesheet>

如果您只想获得一个范围作为结果,请将内部 for-each 替换为以下内容:

...
<xsl:for-each select="key('nd',ReferenceLine)">
    <xsl:sort order="ascending" select="Id" />
    <xsl:if test="position() = 1">
        <xsl:value-of select="Id" />
    </xsl:if>
    <xsl:if test="position() = last() and position() != 1">
        <xsl:value-of select="concat(' - ',Id)" />
    </xsl:if>
</xsl:for-each>
...

但请注意,此范围会忽略间隙,仅使用最低和最高值。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-02
    • 1970-01-01
    • 2020-07-28
    • 2016-01-22
    相关资源
    最近更新 更多