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 使用XSL转换标记序列_Xml_Xslt_If Statement_Foreach - Fatal编程技术网

Xml 使用XSL转换标记序列

Xml 使用XSL转换标记序列,xml,xslt,if-statement,foreach,Xml,Xslt,If Statement,Foreach,我是个新手。我正在尝试使用XSL将一个XML文件转换为另一个具有不同结构的XML文件。XML的输入部分如下所示: <tag> <Keyword>Event: Some Text</Keyword> <Keyword>Group: Some Text</Keyword> <Keyword>Other: Some Text</Keyword> </tag> 事件:一些文本 组:

我是个新手。我正在尝试使用XSL将一个XML文件转换为另一个具有不同结构的XML文件。XML的输入部分如下所示:

<tag>
    <Keyword>Event: Some Text</Keyword>
    <Keyword>Group: Some Text</Keyword>
    <Keyword>Other: Some Text</Keyword>
</tag>

事件:一些文本
组:一些文本
其他:一些文本
我希望所需的输出为:

<tag>
    <event> Some Text </event>
    <group> Some Text </group>
    <other> Some Text </other>
</tag>

一些文本
一些文本
一些文本
我的当前XSL文件:

<xsl:for-each select="tag">
    <xsl:if test="starts-with(Keyword, 'Event: ')">
        <event>
          <xsl:value-of select="substring-after(Keyword, 'Event: ')"/>
        </event>
    </xsl:if>
    <xsl:if test="starts-with(Keyword, 'Group: ')">
        <group>
          <xsl:value-of select="substring-after(Keyword, 'Group: ')"/>
        </group>
    </xsl:if>
    <xsl:if test="starts-with(Keyword, 'Other: ')">
        <other>
          <xsl:value-of select="substring-after(Keyword, 'Other: ')"/>
        </other>
    </xsl:if>
</xsl:for-each>

当前输出仅显示事件节点,不显示其余节点:

<tag>
    <event> Some Text </event>
</tag>

一些文本

我尝试在XSL中用“事件”部分切换“组”部分,但是可能由于输入XML中关键字节点的顺序,没有显示所有子节点。因此,我如何读取所有关键字节点并将它们转换为相应的新节点进行显示?

您只有一个
标记
元素。您希望迭代所有的子项

<xsl:for-each select="tag/*">

    <xsl:if test="starts-with(., 'Event: ')">
        <event>
          <xsl:value-of select="substring-after(., 'Event: ')"/>
        </event>
    </xsl:if>
    <xsl:if test="starts-with(., 'Group: ')">
        <group>
          <xsl:value-of select="substring-after(., 'Group: ')"/>
        </group>
    </xsl:if>
    <xsl:if test="starts-with(., 'Other: ')">
        <other>
          <xsl:value-of select="substring-after(., 'Other: ')"/>
        </other>
    </xsl:if>
</xsl:for-each>

这是我的解决办法。您不必使用xsl:element来创建所有那些if语句

<xsl:template match="tag">
<xsl:apply-templates select="Keyword"/>
</xsl:template>

<xsl:template match="Keyword">
 <xsl:variable name="tag" select="normalize-space(substring-before(.,':'))"/>
 <xsl:value-of select="concat('&lt;',$tag,'&gt;')" disable-output-escaping="yes"/>
 <xsl:value-of select="normalize-space(substring-after(.,':'))"/>
 <xsl:value-of select="concat('&lt;/',$tag,'&gt;')" disable-output-escaping="yes"/>
</xsl:template>

@Pierre:我正确理解最初的问题和您的解决方案;) 您构建XML元素的方式有点老套。XSLT为xml元素的动态构造提供了特殊的设置。因此,您的模板match=“Keyword”可以如下所示

<xsl:template match="Keyword">
  <xsl:variable name="tag" select="normalize-space(substring-before(.,':'))"/>
  <xsl:element name="{$tag}">
    <xsl:value-of select="normalize-space(substring-after(.,':'))"/>
  </xsl:element>
</xsl:template>


<> p>因此,您可以选择轻松地添加属性到输出XML元素,如果需要的话,不必担心禁用输出逃逸等。

您应该查看@彼埃尔的解决方案,并考虑尝试比XSLT中的每个语句多做模板匹配。这是一种不同的做事方式(声明式与过程式),起初有时很难掌握,但它会使开发和维护变得更容易。+1更干净。我本来想在我的答案中加上类似的东西,但你抢先了我一步!啊。。。你可能是对的。我使用@disable output escaping='yes'将xsl:element更改为xsl:value of。为什么不使用xsl:element和xsl:attribute在运行时动态构造元素?对于元素构造来说,这要好得多,但是,在这种情况下,简单的连接可能会起作用。在这里,我们需要生成元素的名称,而不是它的一个属性。我更喜欢原始代码。您所需要做的就是将表达式包装在
{}
中,以便将表达式作为属性值模板进行计算。禁用输出转义以卡住输出中的尖括号是一种不应使用的恶意攻击。
<xsl:template match="Keyword">
  <xsl:variable name="tag" select="normalize-space(substring-before(.,':'))"/>
  <xsl:element name="{$tag}">
    <xsl:value-of select="normalize-space(substring-after(.,':'))"/>
  </xsl:element>
</xsl:template>