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
使用xslt连接来自不同xpath的数据_Xslt - Fatal编程技术网

使用xslt连接来自不同xpath的数据

使用xslt连接来自不同xpath的数据,xslt,Xslt,我正在尝试使用XSLT进行xml转换。我有以下xml: <myxml> <dataType1> <value1> A1 </value1> <value2> A2 </value2> </dataType1> <dataType1> <value1> B1 </value1>

我正在尝试使用XSLT进行xml转换。我有以下xml:

<myxml>
<dataType1>
    <value1>
        A1
    </value1>
    <value2>
        A2
    </value2>
</dataType1>
<dataType1>
    <value1>
        B1
    </value1>
    <value2>
        B2
    </value2>
</dataType1>
<dataType2>
    <value1>
        A1
    </value1>
    <value3>
        A3
    </value3>
</dataType2>
<dataType2>
    <value1>
        B1
    </value1>
    <value3>
        B3
    </value3>
</dataType2>

A1
A2
地下一层
地下二层
A1
A3
地下一层
地下三层

每个datatype2都有一个元素value1,它是datatype2中的外键,因此我必须基于value1映射此数据

如果存在一个值为1=A1的dataType1和一个值为1=A1的dataType2,那么我必须创建一个值为value2和value3的xml,因此结果如下:

<resultxml>
<data>
    <value2>
        A2
    </value2>
    <value3>
        A3
    </value3>
</data>
<data>
    <value2>
        B2
    </value2>
    <value3>
        B3
    </value3>
</data>

A2
A3
地下二层
地下三层

我想在读取dataType1时动态创建变量,然后在读取datatype2时调用它们,但当我在某个论坛上阅读时,这是不可能的,所以我的问题是:是否可以按照我解释的那样做?如果是,我必须遵循哪种方法(欢迎举例)


提前感谢

这里是XSLT 2.0样式表:

<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  version="2.0">

  <xsl:key name="k1" match="dataType2" use="normalize-space(value1)"/>

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

  <xsl:template match="dataType1[key('k1', value1)]">
    <data>
      <xsl:apply-templates select="node() except value1, key('k1', normalize-space(value1))/*[not(self::value1)]"/>
    </data>
  </xsl:template>

  <xsl:template match="dataType1[not(key('k1', normalize-space(value1)))] | dataType2"/>

</xsl:stylesheet>
<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  version="1.0">

  <xsl:key name="k1" match="dataType2" use="normalize-space(value1)"/>

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

  <xsl:template match="dataType1">
    <xsl:variable name="refs" select="key('k1', normalize-space(value1))"/>
    <xsl:if test="$refs">
      <data>
        <xsl:apply-templates select="node()[not(self::value1)] | $refs/*[not(self::value1)]"/>
      </data>
    </xsl:if>
  </xsl:template>

  <xsl:template match="dataType2"/>

</xsl:stylesheet>

当上述样式表应用于输入时

<myxml>
<dataType1>
    <value1>
        A1
    </value1>
    <value2>
        A2
    </value2>
</dataType1>
<dataType1>
    <value1>
        B1
    </value1>
    <value2>
        B2
    </value2>
</dataType1>
<dataType2>
    <value1>
        A1
    </value1>
    <value3>
        A3
    </value3>
</dataType2>
<dataType2>
    <value1>
        B1
    </value1>
    <value3>
        B3
    </value3>
</dataType2>
</myxml>

A1
A2
地下一层
地下二层
A1
A3
地下一层
地下三层
使用Saxon 9.4,结果是

<?xml version="1.0" encoding="UTF-8"?><myxml>
<dataType1>
    <value1>
        A1
    </value1>
    <value2>
        A2
    </value2>
</dataType1>
<dataType1>
    <value1>
        B1
    </value1>
    <value2>
        B2
    </value2>
</dataType1>


</myxml>

A1
A2
地下一层
地下二层
使用XSLT1.0,您不能在匹配模式中使用键,因此需要更多的代码,稍后我将添加一个示例

[编辑] 以下是XSLT 1.0样式表:

<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  version="2.0">

  <xsl:key name="k1" match="dataType2" use="normalize-space(value1)"/>

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

  <xsl:template match="dataType1[key('k1', value1)]">
    <data>
      <xsl:apply-templates select="node() except value1, key('k1', normalize-space(value1))/*[not(self::value1)]"/>
    </data>
  </xsl:template>

  <xsl:template match="dataType1[not(key('k1', normalize-space(value1)))] | dataType2"/>

</xsl:stylesheet>
<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  version="1.0">

  <xsl:key name="k1" match="dataType2" use="normalize-space(value1)"/>

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

  <xsl:template match="dataType1">
    <xsl:variable name="refs" select="key('k1', normalize-space(value1))"/>
    <xsl:if test="$refs">
      <data>
        <xsl:apply-templates select="node()[not(self::value1)] | $refs/*[not(self::value1)]"/>
      </data>
    </xsl:if>
  </xsl:template>

  <xsl:template match="dataType2"/>

</xsl:stylesheet>

我的提案

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
    <xsl:output method="xml" encoding="UTF-8" indent="no" />
    <xsl:template match="/">
        <resultxml>
            <xsl:for-each select="/myxml/dataType1">
                <xsl:variable name="fk" select="value1" />
                <data>
                    <xsl:copy-of select="value2" />
                    <xsl:copy-of select="/myxml/dataType2[value1 = $fk]/value3" />
                </data>
            </xsl:for-each>
        </resultxml>
    </xsl:template>
</xsl:stylesheet>

此转换:

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

 <xsl:key name="kType1" match="dataType1" use="normalize-space(value1)"/>

 <xsl:template match="dataType2[key('kType1', normalize-space(value1))]">
     <data>
       <value2>
         <xsl:value-of select="key('kType1', normalize-space(value1))/value2"/>
       </value2>
       <xsl:copy-of select="value3"/>
     </data>
 </xsl:template>
 <xsl:template match="text()"/>
</xsl:stylesheet>
<myxml>
    <dataType1>
        <value1>
        A1
        </value1>
        <value2>
        A2
        </value2>
    </dataType1>
    <dataType1>
        <value1>
        B1
        </value1>
        <value2>
        B2
        </value2>
    </dataType1>
    <dataType2>
        <value1>
        A1
        </value1>
        <value3>
        A3
        </value3>
    </dataType2>
    <dataType2>
        <value1>
        B1
        </value1>
        <value3>
        B3
        </value3>
    </dataType2>
</myxml>
<data>
   <value2>
        A2
   </value2>
   <value3>
        A3
   </value3>
</data>
<data>
   <value2>
        B2
   </value2>
   <value3>
        B3
   </value3>
</data>

应用于提供的XML文档时

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

 <xsl:key name="kType1" match="dataType1" use="normalize-space(value1)"/>

 <xsl:template match="dataType2[key('kType1', normalize-space(value1))]">
     <data>
       <value2>
         <xsl:value-of select="key('kType1', normalize-space(value1))/value2"/>
       </value2>
       <xsl:copy-of select="value3"/>
     </data>
 </xsl:template>
 <xsl:template match="text()"/>
</xsl:stylesheet>
<myxml>
    <dataType1>
        <value1>
        A1
        </value1>
        <value2>
        A2
        </value2>
    </dataType1>
    <dataType1>
        <value1>
        B1
        </value1>
        <value2>
        B2
        </value2>
    </dataType1>
    <dataType2>
        <value1>
        A1
        </value1>
        <value3>
        A3
        </value3>
    </dataType2>
    <dataType2>
        <value1>
        B1
        </value1>
        <value3>
        B3
        </value3>
    </dataType2>
</myxml>
<data>
   <value2>
        A2
   </value2>
   <value3>
        A3
   </value3>
</data>
<data>
   <value2>
        B2
   </value2>
   <value3>
        B3
   </value3>
</data>

A1
A2
地下一层
地下二层
A1
A3
地下一层
地下三层
生成所需的正确结果

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

 <xsl:key name="kType1" match="dataType1" use="normalize-space(value1)"/>

 <xsl:template match="dataType2[key('kType1', normalize-space(value1))]">
     <data>
       <value2>
         <xsl:value-of select="key('kType1', normalize-space(value1))/value2"/>
       </value2>
       <xsl:copy-of select="value3"/>
     </data>
 </xsl:template>
 <xsl:template match="text()"/>
</xsl:stylesheet>
<myxml>
    <dataType1>
        <value1>
        A1
        </value1>
        <value2>
        A2
        </value2>
    </dataType1>
    <dataType1>
        <value1>
        B1
        </value1>
        <value2>
        B2
        </value2>
    </dataType1>
    <dataType2>
        <value1>
        A1
        </value1>
        <value3>
        A3
        </value3>
    </dataType2>
    <dataType2>
        <value1>
        B1
        </value1>
        <value3>
        B3
        </value3>
    </dataType2>
</myxml>
<data>
   <value2>
        A2
   </value2>
   <value3>
        A3
   </value3>
</data>
<data>
   <value2>
        B2
   </value2>
   <value3>
        B3
   </value3>
</data>

A2
A3
地下二层
地下三层

这是1:1的关系吗?如果存在多个具有相应值1的dataType2,会发生什么情况?