【问题标题】:Change Hierarchy of xml node based on occurrence根据出现更改xml节点的层次结构
【发布时间】:2019-04-12 16:32:59
【问题描述】:

我正在尝试根据出现的次数将节点移动到其前一个节点下的同一级别。用 XSLT 代码试试这个。

Pay,Remit,Trailer 可以在 xml 中重复。但是每次付款之后都会有n个汇款节点。 在哪里输出。 pay 应该包含它下面的所有汇款节点。

我尝试过使用 XSLT 代码,但不知何故我没有得到预期的结果。

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output  method="xml" encoding='UTF-8'/>
<!--Identity template, 
        provides default behavior that copies all content into the output -->

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

    <xsl:for-each select="pay">
    <xsl:template match="Remit">
        <xsl:value-of select="."/>
        </xsl:template>
    </xsl:for-each>


</xsl:stylesheet>

输入 -

<?xml version="1.0" encoding="utf-8"?>
<Message>
<Record>
    <Header>
        <H></H>
    </Header>
    <Trailer>
        <AA>1</AA>
    </Trailer>
    <Pay>
        <BB>1</BB>
        <amount>11</amount>
    </Pay>
    <Remit>
        <Type>30</Type>
        <Transaction>I</Transaction>
    </Remit>
    <Trailer>
        <AA>1</AA>
    </Trailer>
    <Pay>
        <BB>1</BB>
        <amount>78</amount>
    </Pay>
    <Remit>
        <Type>30</Type>
        <Transaction>I</Transaction>
    </Remit>
    <Remit>
        <Type>30</Type>
        <Transaction>I</Transaction>
    </Remit>
    <Trailer>
        <AA>1</AA>
    </Trailer>
</Record>
</Message>

预期输出:

<?xml version="1.0" encoding="utf-8"?>
<Message>
<Record>
    <Header>
        <H>1</H>
    </Header>`enter code here`
    <Trailer>
        <AA>1</AA>
    </Trailer>
    <Pay>
        <BB>1</BB>
        <amount>11</amount>
        <Remit>
        <Type>30</Type>
        <Transaction>I</Transaction>
            </Remit>
    </Pay>
    <Trailer>
        <AA>1</AA>
    </Trailer>
    <Pay>
        <BB>1</BB>
        <amount>78</amount>
            <Remit>
        <Type>30</Type>
        <Transaction>I</Transaction>
            </Remit>
            <Remit>
        <Type>30</Type>
        <Transaction>I</Transaction>
            </Remit>
    </Pay>
    <Trailer>
        <AA>1</AA>
    </Trailer>
</Record>
</Message>

【问题讨论】:

    标签: xml xslt xslt-1.0 xslt-2.0


    【解决方案1】:

    for-each-group group-starting-with (https://www.w3.org/TR/xslt20/#xsl-for-each-group) 的简单用例:

    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        xmlns:xs="http://www.w3.org/2001/XMLSchema"
        exclude-result-prefixes="#all"
        version="3.0">
    
      <xsl:output indent="yes"/>
      <xsl:strip-space elements="*"/>
    
      <xsl:mode on-no-match="shallow-copy"/>
    
      <xsl:template match="Record">
          <xsl:copy>
              <xsl:for-each-group select="*" group-starting-with="Pay">
                  <xsl:choose>
                      <xsl:when test="self::Pay">
                          <xsl:copy>
                              <xsl:apply-templates select="node(), current-group()[self::Remit]"/>
                          </xsl:copy>
                          <xsl:apply-templates select="(current-group() except .)[not(self::Remit)]"/>
                      </xsl:when>
                      <xsl:otherwise>
                          <xsl:apply-templates select="current-group()"/>
                      </xsl:otherwise>
                  </xsl:choose>
              </xsl:for-each-group>
          </xsl:copy>
      </xsl:template>
    
    </xsl:stylesheet>
    

    https://xsltfiddle.liberty-development.net/3NJ38Zm

    对于 XSLT 2 处理器,将 xsl:mode 声明替换为您的标识模板

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

    【讨论】:

    • javax.xml.transform.TransformerException: java.lang.RuntimeException: com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform 中不支持的 XSL 元素“w3.org/1999/XSL/Transform:for-each-group” (TransformerImpl.java:737) at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform(TransformerImpl.java:343) @Martin,我猜我的工具正在使用一些旧的 java 处理器。还有一种方法可以使用 xslt 转换实现这一目标
    • 那你为什么要用xslt-2.0这个标签呢?无论如何,在 Java 平台上,通常很容易将 Saxon 9 HE(sourceforge.net/projects/saxon/files/Saxon-HEmvnrepository.com/artifact/net.sf.saxon/Saxon-HE)放在类路径上并让它执行 XSLT 2 或 3。
    猜你喜欢
    • 2022-01-06
    • 1970-01-01
    • 2019-07-27
    • 2015-06-12
    • 1970-01-01
    • 2020-01-04
    • 1970-01-01
    • 1970-01-01
    • 2019-11-19
    相关资源
    最近更新 更多