2

我正在尝试为其他人解决此问题,但我自己也遇到了问题。

我有 XML:

<Process>
  <name>Pro1</name>
  <duration>Dur1</duration>
  <time>Time1</time>
  <name>Pro2</name>
  <duration>Dur2</duration>
  <time>Time2</time>
  <name>Pro3</name>
  <duration>Dur3</duration>
  <time>Time3</time>
  <name>Pro4</name>
  <duration>Dur4</duration>
  <time>Time4</time>
  <name>Pro5</name>
  <duration>Dur5</duration>
  <time>Time5</time>
</Process>

输出:

<Process>
  <Process_Info>
    <name>Pro1</name>
    <duration>Dur1</duration>
    <time>Time1</time>
  </Process_Info>
  <Process_Info>
    <name>Pro2</name>
    <duration>Dur2</duration>
    <time>Time2</time>
  </Process_Info>
  <Process_Info>
    <name>Pro3</name>
    <duration>Dur3</duration>
    <time>Time3</time>
  </Process_Info>
  <Process_Info>
    <name>Pro4</name>
    <duration>Dur4</duration>
    <time>Time4</time>
  </Process_Info>
  <Process_Info>
    <name>Pro5</name>
    <duration>Dur5</duration>
    <time>Time5</time>
  </Process_Info>
</Process>

使用 XSLT:

<xsl:stylesheet version="1.0" 
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>

  <xsl:variable name ="varProcess" select ="Process"/>

  <xsl:template match="Process">
    <xsl:element name="Process">
      <xsl:for-each select ="name">
        <xsl:variable name ="posName" select ="position()"/>
        <xsl:element name ="Process_Info">
          <xsl:copy-of select ="."/>
          <xsl:copy-of select="$varProcess/duration[$posName]"/>
          <xsl:copy-of select="$varProcess/time[$posName]"/>
        </xsl:element>
      </xsl:for-each>
    </xsl:element>
  </xsl:template>
</xsl:stylesheet>

但是,<duration>and<time>节点并不总是存在,并且<name>是唯一受保证的节点。因此,如果缺少一个,我的position()选择就会失败。

如何更改 XSLT 以使其即使在<duration>和/或<time>不存在时也能正常工作。

我的理论是您选择当前名称节点下方的两个节点,如果它们是<duration><time>它们被复制?但也不确定这将如何实施。

导致问题的电流输出示例。

输入:

<Process>
  <name>Pro1</name>
  <duration>Dur1</duration>
  <time>Time1</time>
  <name>Pro2</name>
  <duration>Dur2</duration>
  <time>Time2</time>
  <name>Pro3</name>
  <duration>Dur3</duration>
  <time>Time3</time>
  <name>Pro4</name>
  <time>Time4</time>
  <name>Pro5</name>
  <duration>Dur5</duration>
</Process>

输出:

<Process>
  <Process_Info>
    <name>Pro1</name>
    <duration>Dur1</duration>
    <time>Time1</time>
  </Process_Info>
  <Process_Info>
    <name>Pro2</name>
    <duration>Dur2</duration>
    <time>Time2</time>
  </Process_Info>
  <Process_Info>
    <name>Pro3</name>
    <duration>Dur3</duration>
    <time>Time3</time>
  </Process_Info>
  <Process_Info>
    <name>Pro4</name>
    <duration>Dur5</duration> <!-- Should be in the below process_info -->
    <time>Time4</time>
  </Process_Info>
  <Process_Info>
    <name>Pro5</name>
  </Process_Info>
</Process>
4

3 回答 3

2

这可以解决问题,尽管方法有点“手动”。可能有更优雅的方法来实现这一点

<xsl:template match="Process">
    <xsl:element name="Process">
        <xsl:for-each select ="name">
            <xsl:element name ="Process_Info">
                <xsl:copy-of select ="."/>
                <xsl:variable name="firstSib" select="local-name(following-sibling::*[1])" />
                <xsl:variable name="secondSib" select="local-name(following-sibling::*[2])" />
                <xsl:choose>
                    <xsl:when test="$firstSib='duration'">
                        <xsl:copy-of select="following-sibling::*[1]"/>
                        <xsl:choose>
                            <xsl:when test="$secondSib='time'">
                                <xsl:copy-of select="following-sibling::*[2]"/>
                            </xsl:when>
                            <xsl:otherwise>
                                <time>SomeDefaultValueForMissingTime</time>
                            </xsl:otherwise>
                        </xsl:choose>
                    </xsl:when>
                    <xsl:when test="$firstSib='time'">
                        <duration>SomeDefaultValueForMissingDuration</duration>
                        <xsl:copy-of select="following-sibling::*[1]"/>
                    </xsl:when>
                    <xsl:otherwise>
                        <duration>SomeDefaultValueForMissingDuration</duration>
                        <time>SomeDefaultValueForMissingTime</time>
                    </xsl:otherwise>
                </xsl:choose>
            </xsl:element>
        </xsl:for-each>
    </xsl:element>
</xsl:template>

输入 :

<Process>
    <name>Pro1</name>
    <duration>Dur1</duration>
    <time>Time1</time>
    <name>NameMissingDuration</name>
    <time>TimeMissingDuration</time>
    <name>NameMissingTime</name>
    <duration>DurMissingTime</duration>
    <name>NameMissingBoth</name>
    <name>NormalName</name>
    <duration>NormalDuration</duration>
    <time>NormalTime</time>
</Process>

输出

<Process>
  <Process_Info>
    <name>Pro1</name>
    <duration>Dur1</duration>
    <time>Time1</time>
  </Process_Info>
  <Process_Info>
    <name>NameMissingDuration</name>
    <duration>SomeDefaultValueForMissingDuration</duration>
    <time>TimeMissingDuration</time>
  </Process_Info>
  <Process_Info>
    <name>NameMissingTime</name>
    <duration>DurMissingTime</duration>
    <time>SomeDefaultValueForMissingTime</time>
  </Process_Info>
  <Process_Info>
    <name>NameMissingBoth</name>
    <duration>SomeDefaultValueForMissingDuration</duration>
    <time>SomeDefaultValueForMissingTime</time>
  </Process_Info>
  <Process_Info>
    <name>NormalName</name>
    <duration>NormalDuration</duration>
    <time>NormalTime</time>
  </Process_Info>
</Process>
于 2012-07-18T08:42:07.010 回答
2

这是没有xsl:if.

这演示了在选择当前名称元素之后的第一个时间(或持续时间)元素时使用该函数测试节点是否相等generate-id(),并且其第一个前面的名称元素是当前元素。

<xsl:stylesheet version="1.0" 
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>

  <xsl:template match="Process">
    <xsl:copy>
      <xsl:apply-templates select="name"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="name">
    <xsl:variable name="this" select="generate-id()"/>
    <Process_Info>
      <xsl:copy-of select="."/>
      <xsl:copy-of select="following-sibling::duration
                           [generate-id(preceding-sibling::name[1]) = $this]
                           [1]"/>
      <xsl:copy-of select="following-sibling::time
                           [generate-id(preceding-sibling::name[1]) = $this]
                           [1]"/>
    </Process_Info>
  </xsl:template>

</xsl:stylesheet>
于 2012-07-18T11:26:10.067 回答
1

根据 nonnb 的响应,所有功劳归于他,最终使用了 XSLT。我的错误是没有包括我不需要填充节点的问题。

<xsl:stylesheet version="1.0" 
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>

  <xsl:template match="Process">
    <xsl:element name="Process">
      <xsl:for-each select ="name">
        <xsl:element name ="Process_Info">
          <xsl:copy-of select ="."/>
          <xsl:variable name="firstSib" select="local-name(following-sibling::*[1])" />
          <xsl:variable name="secondSib" select="local-name(following-sibling::*[2])" />
          <xsl:if test ="($firstSib='duration') or ($firstSib='time')">
            <xsl:copy-of select="following-sibling::*[1]"/>
          </xsl:if>
          <xsl:if test ="($secondSib='duration') or ($secondSib='time')">
            <xsl:copy-of select="following-sibling::*[2]"/>
          </xsl:if>
        </xsl:element>
      </xsl:for-each>
    </xsl:element>
  </xsl:template>
</xsl:stylesheet>
于 2012-07-18T09:47:43.640 回答