Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/xslt/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
检索XML节点位置之间的值_Xml_Xslt_Xpath_Xslt 2.0 - Fatal编程技术网

检索XML节点位置之间的值

检索XML节点位置之间的值,xml,xslt,xpath,xslt-2.0,Xml,Xslt,Xpath,Xslt 2.0,我试图从前面的元素中检索值。但是,我尝试检索的值需要在某个位置之后、其他节点位置之前。我该怎么做 示例XML: <?xml version="1.0" encoding="UTF-8"?> <actions> <action> <code>tr</code> <value>503</value> </action> <action>

我试图从前面的元素中检索值。但是,我尝试检索的值需要在某个位置之后、其他节点位置之前。我该怎么做

示例XML:

<?xml version="1.0" encoding="UTF-8"?>
<actions>
    <action>
        <code>tr</code>
        <value>503</value>
    </action>
    <action>
        <code>co</code>
        <value>0</value>
    </action>
    <action>
        <code>cou</code>
        <value>0</value>
    </action>
    <action>
        <code>tr</code>
        <value>87</value>
    </action>
    <action>
        <code>st</code>
        <value>0</value>
    </action>
    <action>
        <code>wta</code>
        <value>0</value>
    </action>
    <action>
        <code>pi</code>
        <value>0</value>
    </action>
    <action>
        <code>tr</code>
        <value>64</value>
    </action>
    <action>
        <code>st</code>
        <value>0</value>
    </action>
    <action>
        <code>del</code>
        <value>0</value>
    </action>
    <action>
        <code>tr</code>
        <value>27</value>
    </action>
    <action>
        <code>wa</code>
        <value>0</value>
    </action>
    <action>
        <code>dec</code>
        <value>0</value>
    </action>
</actions>
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions" exclude-result-prefixes="xs fn">
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

    <xsl:template match="/actions">
        <result>
            <!-- Loop through all action elements -->
            <xsl:for-each select="action">
                <!-- Display only the needed action in the result file -->
                <xsl:if test="code = 'co' or code = 'st' or code = 'dec' or code = 'pi' or code = 'del'">
                    <action>
                        <code>
                            <xsl:choose>
                                <xsl:when test="code = 'co'">1</xsl:when>
                                <xsl:when test="code = 'st'">5</xsl:when>
                                <xsl:when test="code = 'dec'">2</xsl:when>
                                <xsl:when test="code = 'pi'">3</xsl:when>
                                <xsl:when test="code = 'del'">4</xsl:when>
                            </xsl:choose>
                        </code>
                        <!-- Get some positions in variables -->
                        <xsl:variable name="previousPosition"><xsl:value-of select="position() - 1" /></xsl:variable>
                        <xsl:variable name="lastTRPosition"><xsl:value-of select="count((preceding::action[code = 'tr'])[last()]/preceding::action)+1" /></xsl:variable>
                        <xsl:variable name="currentPosition"><xsl:value-of select="position()" /></xsl:variable>
                        <!-- Should be the value of the preceding action element with code 'tr' (last occurence). But only use when between the last preceding action element with code 'tr' and the current node position NO known code is used ('co', 'st', 'dec', 'pi' or 'del') -->
                        <value>
                                    <xsl:choose>
                                        <xsl:when test="(preceding::action[code = 'tr']/value)[last()] != ''"> <!-- some work to do here -->
                                            <xsl:value-of select="round((preceding::action[code = 'tr']/value)[last()])" />
                                        </xsl:when>
                                        <xsl:otherwise>0</xsl:otherwise>
                                    </xsl:choose>
                        </value>
                    </action>
                </xsl:if>
            </xsl:for-each>
        </result>
    </xsl:template>
</xsl:stylesheet>
<?xml version="1.0" encoding="UTF-8"?>
<result>
    <action>
        <code>1</code>
        <value>503</value>
    </action>
    <action>
        <code>5</code>
        <value>87</value>
    </action>
    <action>
        <code>3</code>
        <value>87</value>
    </action>
    <action>
        <code>5</code>
        <value>64</value>
    </action>
    <action>
        <code>4</code>
        <value>64</value>
    </action>
    <action>
        <code>2</code>
        <value>27</value>
    </action>
</result>
<?xml version="1.0" encoding="UTF-8"?>
<result>
    <action>
        <code>1</code>
        <value>503</value>
    </action>
    <action>
        <code>5</code>
        <value>87</value>
    </action>
    <action>
        <code>3</code>
        <value>0</value>
    </action>
    <action>
        <code>5</code>
        <value>64</value>
    </action>
    <action>
        <code>4</code>
        <value>0</value>
    </action>
    <action>
        <code>2</code>
        <value>27</value>
    </action>
</result>
当前XSLT:

<?xml version="1.0" encoding="UTF-8"?>
<actions>
    <action>
        <code>tr</code>
        <value>503</value>
    </action>
    <action>
        <code>co</code>
        <value>0</value>
    </action>
    <action>
        <code>cou</code>
        <value>0</value>
    </action>
    <action>
        <code>tr</code>
        <value>87</value>
    </action>
    <action>
        <code>st</code>
        <value>0</value>
    </action>
    <action>
        <code>wta</code>
        <value>0</value>
    </action>
    <action>
        <code>pi</code>
        <value>0</value>
    </action>
    <action>
        <code>tr</code>
        <value>64</value>
    </action>
    <action>
        <code>st</code>
        <value>0</value>
    </action>
    <action>
        <code>del</code>
        <value>0</value>
    </action>
    <action>
        <code>tr</code>
        <value>27</value>
    </action>
    <action>
        <code>wa</code>
        <value>0</value>
    </action>
    <action>
        <code>dec</code>
        <value>0</value>
    </action>
</actions>
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions" exclude-result-prefixes="xs fn">
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

    <xsl:template match="/actions">
        <result>
            <!-- Loop through all action elements -->
            <xsl:for-each select="action">
                <!-- Display only the needed action in the result file -->
                <xsl:if test="code = 'co' or code = 'st' or code = 'dec' or code = 'pi' or code = 'del'">
                    <action>
                        <code>
                            <xsl:choose>
                                <xsl:when test="code = 'co'">1</xsl:when>
                                <xsl:when test="code = 'st'">5</xsl:when>
                                <xsl:when test="code = 'dec'">2</xsl:when>
                                <xsl:when test="code = 'pi'">3</xsl:when>
                                <xsl:when test="code = 'del'">4</xsl:when>
                            </xsl:choose>
                        </code>
                        <!-- Get some positions in variables -->
                        <xsl:variable name="previousPosition"><xsl:value-of select="position() - 1" /></xsl:variable>
                        <xsl:variable name="lastTRPosition"><xsl:value-of select="count((preceding::action[code = 'tr'])[last()]/preceding::action)+1" /></xsl:variable>
                        <xsl:variable name="currentPosition"><xsl:value-of select="position()" /></xsl:variable>
                        <!-- Should be the value of the preceding action element with code 'tr' (last occurence). But only use when between the last preceding action element with code 'tr' and the current node position NO known code is used ('co', 'st', 'dec', 'pi' or 'del') -->
                        <value>
                                    <xsl:choose>
                                        <xsl:when test="(preceding::action[code = 'tr']/value)[last()] != ''"> <!-- some work to do here -->
                                            <xsl:value-of select="round((preceding::action[code = 'tr']/value)[last()])" />
                                        </xsl:when>
                                        <xsl:otherwise>0</xsl:otherwise>
                                    </xsl:choose>
                        </value>
                    </action>
                </xsl:if>
            </xsl:for-each>
        </result>
    </xsl:template>
</xsl:stylesheet>
<?xml version="1.0" encoding="UTF-8"?>
<result>
    <action>
        <code>1</code>
        <value>503</value>
    </action>
    <action>
        <code>5</code>
        <value>87</value>
    </action>
    <action>
        <code>3</code>
        <value>87</value>
    </action>
    <action>
        <code>5</code>
        <value>64</value>
    </action>
    <action>
        <code>4</code>
        <value>64</value>
    </action>
    <action>
        <code>2</code>
        <value>27</value>
    </action>
</result>
<?xml version="1.0" encoding="UTF-8"?>
<result>
    <action>
        <code>1</code>
        <value>503</value>
    </action>
    <action>
        <code>5</code>
        <value>87</value>
    </action>
    <action>
        <code>3</code>
        <value>0</value>
    </action>
    <action>
        <code>5</code>
        <value>64</value>
    </action>
    <action>
        <code>4</code>
        <value>0</value>
    </action>
    <action>
        <code>2</code>
        <value>27</value>
    </action>
</result>
想要的结果:

<?xml version="1.0" encoding="UTF-8"?>
<actions>
    <action>
        <code>tr</code>
        <value>503</value>
    </action>
    <action>
        <code>co</code>
        <value>0</value>
    </action>
    <action>
        <code>cou</code>
        <value>0</value>
    </action>
    <action>
        <code>tr</code>
        <value>87</value>
    </action>
    <action>
        <code>st</code>
        <value>0</value>
    </action>
    <action>
        <code>wta</code>
        <value>0</value>
    </action>
    <action>
        <code>pi</code>
        <value>0</value>
    </action>
    <action>
        <code>tr</code>
        <value>64</value>
    </action>
    <action>
        <code>st</code>
        <value>0</value>
    </action>
    <action>
        <code>del</code>
        <value>0</value>
    </action>
    <action>
        <code>tr</code>
        <value>27</value>
    </action>
    <action>
        <code>wa</code>
        <value>0</value>
    </action>
    <action>
        <code>dec</code>
        <value>0</value>
    </action>
</actions>
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions" exclude-result-prefixes="xs fn">
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

    <xsl:template match="/actions">
        <result>
            <!-- Loop through all action elements -->
            <xsl:for-each select="action">
                <!-- Display only the needed action in the result file -->
                <xsl:if test="code = 'co' or code = 'st' or code = 'dec' or code = 'pi' or code = 'del'">
                    <action>
                        <code>
                            <xsl:choose>
                                <xsl:when test="code = 'co'">1</xsl:when>
                                <xsl:when test="code = 'st'">5</xsl:when>
                                <xsl:when test="code = 'dec'">2</xsl:when>
                                <xsl:when test="code = 'pi'">3</xsl:when>
                                <xsl:when test="code = 'del'">4</xsl:when>
                            </xsl:choose>
                        </code>
                        <!-- Get some positions in variables -->
                        <xsl:variable name="previousPosition"><xsl:value-of select="position() - 1" /></xsl:variable>
                        <xsl:variable name="lastTRPosition"><xsl:value-of select="count((preceding::action[code = 'tr'])[last()]/preceding::action)+1" /></xsl:variable>
                        <xsl:variable name="currentPosition"><xsl:value-of select="position()" /></xsl:variable>
                        <!-- Should be the value of the preceding action element with code 'tr' (last occurence). But only use when between the last preceding action element with code 'tr' and the current node position NO known code is used ('co', 'st', 'dec', 'pi' or 'del') -->
                        <value>
                                    <xsl:choose>
                                        <xsl:when test="(preceding::action[code = 'tr']/value)[last()] != ''"> <!-- some work to do here -->
                                            <xsl:value-of select="round((preceding::action[code = 'tr']/value)[last()])" />
                                        </xsl:when>
                                        <xsl:otherwise>0</xsl:otherwise>
                                    </xsl:choose>
                        </value>
                    </action>
                </xsl:if>
            </xsl:for-each>
        </result>
    </xsl:template>
</xsl:stylesheet>
<?xml version="1.0" encoding="UTF-8"?>
<result>
    <action>
        <code>1</code>
        <value>503</value>
    </action>
    <action>
        <code>5</code>
        <value>87</value>
    </action>
    <action>
        <code>3</code>
        <value>87</value>
    </action>
    <action>
        <code>5</code>
        <value>64</value>
    </action>
    <action>
        <code>4</code>
        <value>64</value>
    </action>
    <action>
        <code>2</code>
        <value>27</value>
    </action>
</result>
<?xml version="1.0" encoding="UTF-8"?>
<result>
    <action>
        <code>1</code>
        <value>503</value>
    </action>
    <action>
        <code>5</code>
        <value>87</value>
    </action>
    <action>
        <code>3</code>
        <value>0</value>
    </action>
    <action>
        <code>5</code>
        <value>64</value>
    </action>
    <action>
        <code>4</code>
        <value>0</value>
    </action>
    <action>
        <code>2</code>
        <value>27</value>
    </action>
</result>
变化及其原因?

<action>
    <code>3</code>
    <value>87</value> <!-- should be 0 -->
</action>
这应该是0。因为在最后一个
操作/code='tr'
的位置和要写入结果的节点的当前位置()之间,有一个已知的代码'st',它已经有了这个值

<action>
    <code>4</code>
    <value>64</value>
</action>
这应该是0。因为在最后一个
操作/code='tr'
的位置和要写入结果的节点的当前位置()之间,有一个已知的代码'st',它已经有了这个值

<action>
    <code>4</code>
    <value>64</value>
</action>

xsl:when
中获得正确的测试时,我有点被卡住了。有人能帮忙吗?

我建议用
分组,从
开始,然后使用
操作符进行筛选。我还将映射作为一个参数,并使用一个键来高效地映射,因此我得到了

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions" exclude-result-prefixes="xs fn">

    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

    <xsl:key name="code" match="code" use="@from"/>

    <xsl:param name="code-map">
      <code from="co" to="1"/>
      <code from="st" to="5"/>
      <code from="dec" to="2"/>
      <code from="pi" to="3"/>
      <code from="del" to="4"/>
    </xsl:param>

    <xsl:template match="/actions">
        <result>
            <xsl:for-each-group select="action" group-starting-with="action[code = 'tr']">
              <xsl:variable name="tr-head" select="."/>
              <xsl:apply-templates select="current-group()[self::action[code = $code-map/code/@from]]">
                <xsl:with-param name="tr" select="$tr-head"/>
              </xsl:apply-templates>
            </xsl:for-each-group>
        </result>
    </xsl:template>

    <xsl:template match="action">
      <xsl:param name="tr"/>
      <xsl:copy>
        <code>
          <xsl:value-of select="key('code', code, $code-map)/@to"/>
        </code>
        <value>
          <xsl:value-of 
            select="if (not(exists((current-group() except $tr) 
                                    [current() >> . and code = $code-map/code/@from])))
                    then $tr/value else 0"/>
        </value>
      </xsl:copy>
    </xsl:template>

</xsl:stylesheet>
我得到了想要的结果

<result>
   <action>
      <code>1</code>
      <value>503</value>
   </action>
   <action>
      <code>5</code>
      <value>87</value>
   </action>
   <action>
      <code>3</code>
      <value>0</value>
   </action>
   <action>
      <code>5</code>
      <value>64</value>
   </action>
   <action>
      <code>4</code>
      <value>0</value>
   </action>
   <action>
      <code>2</code>
      <value>27</value>
   </action>
</result>

我建议使用
分组,以
开始分组,然后使用
>
操作符进行筛选。我还将映射作为一个参数,并使用一个键来高效地映射,因此我得到了

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions" exclude-result-prefixes="xs fn">

    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

    <xsl:key name="code" match="code" use="@from"/>

    <xsl:param name="code-map">
      <code from="co" to="1"/>
      <code from="st" to="5"/>
      <code from="dec" to="2"/>
      <code from="pi" to="3"/>
      <code from="del" to="4"/>
    </xsl:param>

    <xsl:template match="/actions">
        <result>
            <xsl:for-each-group select="action" group-starting-with="action[code = 'tr']">
              <xsl:variable name="tr-head" select="."/>
              <xsl:apply-templates select="current-group()[self::action[code = $code-map/code/@from]]">
                <xsl:with-param name="tr" select="$tr-head"/>
              </xsl:apply-templates>
            </xsl:for-each-group>
        </result>
    </xsl:template>

    <xsl:template match="action">
      <xsl:param name="tr"/>
      <xsl:copy>
        <code>
          <xsl:value-of select="key('code', code, $code-map)/@to"/>
        </code>
        <value>
          <xsl:value-of 
            select="if (not(exists((current-group() except $tr) 
                                    [current() >> . and code = $code-map/code/@from])))
                    then $tr/value else 0"/>
        </value>
      </xsl:copy>
    </xsl:template>

</xsl:stylesheet>
我得到了想要的结果

<result>
   <action>
      <code>1</code>
      <value>503</value>
   </action>
   <action>
      <code>5</code>
      <value>87</value>
   </action>
   <action>
      <code>3</code>
      <value>0</value>
   </action>
   <action>
      <code>5</code>
      <value>64</value>
   </action>
   <action>
      <code>4</code>
      <value>0</value>
   </action>
   <action>
      <code>2</code>
      <value>27</value>
   </action>
</result>

只是因为我说过,这里有一个xslt-1.0解决方案

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

    <xsl:template match="action" />

    <xsl:template match="action [code = 'co' or code = 'st' or code = 'dec' or code = 'pi' or code = 'del']" >
        <result>
            <xsl:copy>
                <code>
                    <xsl:choose>
                        <xsl:when test="code = 'co'">1</xsl:when>
                        <xsl:when test="code = 'st'">5</xsl:when>
                        <xsl:when test="code = 'dec'">2</xsl:when>
                        <xsl:when test="code = 'pi'">3</xsl:when>
                        <xsl:when test="code = 'del'">4</xsl:when>
                    </xsl:choose>
                </code>
            <value>
                <xsl:variable name="ptr" select="preceding-sibling::action[code='tr'][1]"/>
                <xsl:variable name="trpos" select="count($ptr/preceding-sibling::action)"/>
                <xsl:variable name="pcode" select="preceding-sibling::action[code = 'co' or code = 'st' or code = 'dec' or code = 'pi' or code = 'del'][1]"/>
                <xsl:variable name="codepos" select="count($pcode/preceding-sibling::action)"/>
                <xsl:choose>
                    <xsl:when test="$trpos >= $codepos">
                        <xsl:value-of select="round($ptr/value)" />
                    </xsl:when>
                    <xsl:otherwise>0</xsl:otherwise>
                </xsl:choose>

            </value>
            </xsl:copy>
        </result>

    </xsl:template>
    <xsl:template match="/actions">
        <result>
            <xsl:apply-templates select="action" />
        </result>

    </xsl:template>
</xsl:stylesheet>


1.
5.
2.
3.
4.
0
只是因为我说过,这里是xslt-1.0解决方案

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

    <xsl:template match="action" />

    <xsl:template match="action [code = 'co' or code = 'st' or code = 'dec' or code = 'pi' or code = 'del']" >
        <result>
            <xsl:copy>
                <code>
                    <xsl:choose>
                        <xsl:when test="code = 'co'">1</xsl:when>
                        <xsl:when test="code = 'st'">5</xsl:when>
                        <xsl:when test="code = 'dec'">2</xsl:when>
                        <xsl:when test="code = 'pi'">3</xsl:when>
                        <xsl:when test="code = 'del'">4</xsl:when>
                    </xsl:choose>
                </code>
            <value>
                <xsl:variable name="ptr" select="preceding-sibling::action[code='tr'][1]"/>
                <xsl:variable name="trpos" select="count($ptr/preceding-sibling::action)"/>
                <xsl:variable name="pcode" select="preceding-sibling::action[code = 'co' or code = 'st' or code = 'dec' or code = 'pi' or code = 'del'][1]"/>
                <xsl:variable name="codepos" select="count($pcode/preceding-sibling::action)"/>
                <xsl:choose>
                    <xsl:when test="$trpos >= $codepos">
                        <xsl:value-of select="round($ptr/value)" />
                    </xsl:when>
                    <xsl:otherwise>0</xsl:otherwise>
                </xsl:choose>

            </value>
            </xsl:copy>
        </result>

    </xsl:template>
    <xsl:template match="/actions">
        <result>
            <xsl:apply-templates select="action" />
        </result>

    </xsl:template>
</xsl:stylesheet>


1.
5.
2.
3.
4.
0
Martin,你能解释一下这一行吗,因为我试图在我的总样式表中插入你的解决方案,但我无法让它工作。看起来此行没有给出任何输出。请参见此处的完整源XML和XSLT:问题似乎是由于文档
xmlns=”中的默认名称空间引起的http://www.company.com/log/lk/pl“
。我不太明白why@MarkVeenstra,因为XSLT为元素定义了默认名称空间,所以我设置的
param
中的元素也会在该名称空间中结束,这样路径
$code map/code/@from
就不会选择它们。您需要在参数上添加
,以避免出现该问题。Martin,您能解释一下行
,因为我试图在我拥有的总样式表中插入您的解决方案,但我无法使其工作。看起来此行没有给出任何输出。请参见此处的完整源XML和XSLT:问题似乎是由于文档
xmlns=”中的默认名称空间引起的http://www.company.com/log/lk/pl“
。我不太明白why@MarkVeenstra,因为XSLT为元素定义了默认名称空间,所以我设置的
param
中的元素也会在该名称空间中结束,这样路径
$code map/code/@from
就不会选择它们。您需要在参数上添加
,以避免该问题。