Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/xml/15.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_Xslt 1.0 - Fatal编程技术网

Xml 嵌套元素的多个属性

Xml 嵌套元素的多个属性,xml,xslt,xslt-1.0,Xml,Xslt,Xslt 1.0,我想将下面的示例片段转换为多个元素 <para font="Times" size="12" face="Bold Italic">This is some text.</para> <para font="Times" size="12" face="Bold">This is some more text.</para> 这是一些文本。 这是更多的文本。 我希望将其转换为如下内容: <para> <font name

我想将下面的示例片段转换为多个元素

<para font="Times" size="12" face="Bold Italic">This is some text.</para>
<para font="Times" size="12" face="Bold">This is some more text.</para>
这是一些文本。
这是更多的文本。
我希望将其转换为如下内容:

<para>
   <font name="Times" size="12">
       <b>
           <i>This is some text.</i>
       </b>
    </font>
</para>
<para>
   <font name="Times" size="12">
       <b>This is some text.</b>
    </font>
</para>

这是一些文本。
这是一些文本。
有没有一种方法可以在不使用所有
块的情况下执行此操作。。?上面是具有更多属性和属性值的简单示例


我正在使用XSLT1.0(xsltproc)

我认为您可能仍然会得到一个xsl:choose在这里,将“粗体”和“斜体”之类的词映射到“b”和“I”的元素名称

因此,您可以从一个与@face属性匹配的模板开始,但这个模板也有一个名称,因此可以使用任何有待处理的“face”值递归调用它

<xsl:template match="@face" name="face">
    <xsl:param name="face" select="." />

您可以通过一些简单的字符串处理提取要处理的第一个面名称

<xsl:variable name="facename" select="substring-before(concat($face, ' '), ' ')" />

(此处的concat允许参数中有一个单词)

然后可以映射到这样的元素名

    <xsl:variable name="element">
        <xsl:choose>
            <xsl:when test="$facename = 'Bold'">b</xsl:when>
            <xsl:when test="$facename = 'Italic'">i</xsl:when>
        </xsl:choose>
    </xsl:variable>

B
我
话虽如此,理论上您可以在一个单独的XML文件中维护映射,并使用document函数来查找它们

最后,您将使用xsl:choose输出元素(如果找到),或者处理父元素的子元素

    <xsl:choose>
        <xsl:when test="$element != ''">
            <xsl:element name="{$element}">
                <xsl:call-template name="face">
                    <xsl:with-param name="face" select="normalize-space(substring-after($face, $facename))" />
                </xsl:call-template>
            </xsl:element>
        </xsl:when>
        <xsl:otherwise>
            <xsl:apply-templates select="../node()" />
        </xsl:otherwise>
    </xsl:choose>

试试这个XSLT

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

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

    <xsl:template match="*[@font]">
        <xsl:copy>
            <font>
                <xsl:apply-templates select="@*[name() != 'face']"/>
                <xsl:apply-templates select="@face" />
            </font>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="@face" name="face">
        <xsl:param name="face" select="." />

        <xsl:variable name="facename" select="substring-before(concat($face, ' '), ' ')" />

        <xsl:variable name="element">
            <xsl:choose>
                <xsl:when test="$facename = 'Bold'">b</xsl:when>
                <xsl:when test="$facename = 'Italic'">i</xsl:when>
            </xsl:choose>
        </xsl:variable>

        <xsl:choose>
            <xsl:when test="$element != ''">
                <xsl:element name="{$element}">
                    <xsl:call-template name="face">
                        <xsl:with-param name="face" select="normalize-space(substring-after($face, $facename))" />
                    </xsl:call-template>
                </xsl:element>
            </xsl:when>
            <xsl:otherwise>
                <xsl:apply-templates select="../node()" />
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>
</xsl:stylesheet>

B
我

假设@face的值实际上对应于输出中的元素名称(已经有几个人对此发表了评论),您可以这样做

递归命名模板实际上标记了
@face
属性的内容,以确定嵌套序列

样式表

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:exsl="http://exslt.org/common"
    extension-element-prefixes="exsl">

    <xsl:strip-space elements="*"/>
    <xsl:output omit-xml-declaration="yes" indent="yes" />

    <xsl:template match="/root">
        <xsl:copy>
            <xsl:apply-templates/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="para">
        <xsl:copy>
            <font name="{@font}" size="{@size}">
                        <xsl:call-template name="tokenize">
                            <xsl:with-param name="string" select="@face"/>
                            <xsl:with-param name="delim" select="' '"/>
                        </xsl:call-template>
            </font>
        </xsl:copy>
    </xsl:template>

    <xsl:template name="tokenize">
      <xsl:param name="string" />
      <xsl:param name="delim" />

      <xsl:choose>
        <xsl:when test="contains($string, $delim)">
          <xsl:element name="{substring-before($string,$delim)}">
            <xsl:call-template name="tokenize">
            <xsl:with-param name="string" select="substring-after($string, $delim)" />
            <xsl:with-param name="delim" select="$delim" />
          </xsl:call-template>
          </xsl:element>
        </xsl:when>
        <xsl:otherwise>
          <xsl:element name="{$string}">
            <xsl:apply-templates/>
          </xsl:element>
        </xsl:otherwise>
      </xsl:choose>
    </xsl:template>

</xsl:stylesheet>
结果是:

<root>
   <para>
      <font name="Times" size="12">
         <i>
            <b>
               <u>
                  <s>This is some text.</s>
               </u>
            </b>
         </i>
      </font>
   </para>
   <para>
      <font name="Times" size="12">
         <i>
            <b>This is some more text.</b>
         </i>
      </font>
   </para>
</root>

这是一些文本。
这是更多的文本。

我编写了一个样式表,其中包含一个表,您可以在其中添加样式并将它们与标记关联。例如,您可以为
替换
,或者添加新的
。该表可通过
$tags
变量访问,并用于选择与
属性样式名称对应的标记

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:my="my-namespace" exclude-result-prefixes="my" version="1.0">

    <xsl:output indent="yes"/>
    <xsl:strip-space elements="*"/>

    <my:styles>
        <tag name="b" style="Bold"/>
        <tag name="i" style="Italic"/>
        <tag name="u" style="Underline"/>
    </my:styles>

    <xsl:variable name="tags" select="document('')//tag" />

    <xsl:template match="/">
        <xsl:apply-templates select="document/para" mode="initial" />
    </xsl:template>

    <xsl:template match="para" mode="initial">
        <xsl:copy>
            <font name="{@font}" size="{@size}">
                <xsl:choose>
                    <xsl:when test="@face">
                        <xsl:call-template name="add-style">
                            <xsl:with-param name="styles" select="concat(@face,' ')"/>
                        </xsl:call-template>
                    </xsl:when>
                    <xsl:otherwise>
                        <xsl:value-of select="."/>
                    </xsl:otherwise>
                </xsl:choose>
            </font>
        </xsl:copy>
    </xsl:template>

    <xsl:template name="add-style">
        <xsl:param name="styles"/>
        <xsl:param name="current-style" select="substring-before($styles, ' ')"/>
        <xsl:message>value:<xsl:value-of select="$styles"/>:</xsl:message>
        <xsl:if test="$current-style">
            <xsl:element name="{$tags[@style = $current-style]/@name}">
                <xsl:call-template name="add-style">
                    <xsl:with-param name="styles" select="substring-after($styles, ' ')"/>
                </xsl:call-template>
                <xsl:if test="not(contains(substring-after($styles, ' '), ' '))">
                    <xsl:value-of select="." />
                </xsl:if>
            </xsl:element>
        </xsl:if>
    </xsl:template>

</xsl:stylesheet>

值::
如果您将其用作输入:

<document>
    <para font="Times" size="12" face="Bold Italic">This is some text.</para>
    <para font="Times" size="12" face="Bold">This is some more text.</para>
    <para font="Times" size="12" face="Italic Bold Underline">This is some text 3.</para>
    <para font="Times" size="12" face="Italic">This is some more text 4.</para>
    <para font="Times" size="12">This is some more text 4.</para>
</document>

这是一些文本。
这是更多的文本。
这是一些文本3。
这是更多的文本4。
这是更多的文本4。
您将得到以下结果:

<para>
   <font name="Times" size="12">
      <b>
         <i>This is some text.</i>
      </b>
   </font>
</para>
<para>
   <font name="Times" size="12">
      <b>This is some more text.</b>
   </font>
</para>
<para>
   <font name="Times" size="12">
      <i>
         <b>
            <u>This is some text 3.</u>
         </b>
      </i>
   </font>
</para>
<para>
   <font name="Times" size="12">
      <i>This is some more text 4.</i>
   </font>
</para>
<para>
   <font name="Times" size="12">This is some more text 4.</font>
</para>

这是一些文本。
这是更多的文本。
这是一些文本3。
这是更多的文本4。
这是更多的文本4。
我没有使用大的选择,但我必须使用一个来说明
face
属性可能不存在的情况


如果
face
属性中有额外的空格,它将失败,因为我使用空格(甚至添加一个)来控制递归。但是这可以通过
normalize-space()

解决。为什么第二个
段落有
face=“Bold”
并导致
这是一些文本。
?此外,规则也不明确。
应该始终是外部元素吗?最后,这方面的解决方案可能对您没有用处,因为这是一个“简单的示例”,您实际上拥有“更多的属性和值”。如果简化XML,请确保保留与问题相关的复杂性。老鼠,你是对的。我有一个拼写错误被修正了。我认为这是一个典型的例子。问题的顺序并不重要。这个问题没有“明确定义”。首先,如果没有某种查找数组,就无法将“粗体”转换为
,将“斜体”转换为
。我们需要知道查找过程中包含了什么(或者至少可以包含什么)。如果只是@face属性中列出的样式,那么这可能相对简单。如果是“更多属性和属性值”,那么可能不是。也许不是最“定义明确”的问题,但所有答案都很好,帮助我以不同的方式看待问题。最后,我只使用了一个带有查找文件的递归模板。
<para>
   <font name="Times" size="12">
      <b>
         <i>This is some text.</i>
      </b>
   </font>
</para>
<para>
   <font name="Times" size="12">
      <b>This is some more text.</b>
   </font>
</para>
<para>
   <font name="Times" size="12">
      <i>
         <b>
            <u>This is some text 3.</u>
         </b>
      </i>
   </font>
</para>
<para>
   <font name="Times" size="12">
      <i>This is some more text 4.</i>
   </font>
</para>
<para>
   <font name="Times" size="12">This is some more text 4.</font>
</para>