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
XSLT1.0和标记化属性_Xslt_Xslt 1.0_Tokenize - Fatal编程技术网

XSLT1.0和标记化属性

XSLT1.0和标记化属性,xslt,xslt-1.0,tokenize,Xslt,Xslt 1.0,Tokenize,[编辑]帖子更新了修订后的XML和预期输出,详见Vincent Biragnet的回答和评论 我正在尝试编写一些代码,将XML数据转换为基于文本的元文件。我没有运气让它吐出期望的输出,目前有点卡住了,所以任何帮助都将不胜感激 XSLT1.0并没有使标记化变得容易,这就是我遇到的问题:我希望将@syn作为CSV字符串处理,并在需要时将其拆分 我正在处理以下XML数据(请注意,除节点外,此XML文件中的所有节点都可以有任何名称。) 我当前的XSL: <?xml version="1.0"?&g

[编辑]帖子更新了修订后的XML和预期输出,详见Vincent Biragnet的回答和评论

我正在尝试编写一些代码,将XML数据转换为基于文本的元文件。我没有运气让它吐出期望的输出,目前有点卡住了,所以任何帮助都将不胜感激

XSLT1.0并没有使标记化变得容易,这就是我遇到的问题:我希望将@syn作为CSV字符串处理,并在需要时将其拆分

我正在处理以下XML数据(请注意,除节点外,此XML文件中的所有节点都可以有任何名称。)

我当前的XSL:

<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output method="text" indent="yes"/>
    <xsl:template match="/Meta"><xsl:apply-templates/></xsl:template>
    <xsl:template match="child::*"><xsl:call-template name="master"/><xsl:apply-templates/></xsl:template>
    <xsl:template name="master">
        <xsl:choose>
            <xsl:when test="count(child::*) = 0">
                <xsl:value-of select="local-name()"/>
                <xsl:apply-templates select="@syn"/>
            </xsl:when>
            <xsl:otherwise>
                [<xsl:value-of select="local-name()"/>]
                <xsl:apply-templates select="@syn"/>
        </xsl:otherwise>
        </xsl:choose>
    </xsl:template>
    <xsl:template name="tokenize" match="@syn">
        <xsl:param name="text" select="."/>
        <xsl:param name="separator" select="','"/>
        <xsl:value-of select="$text"/>
        <xsl:choose>
            <xsl:when test="not(contains($text, $separator))">
                {<xsl:value-of select="normalize-space($text)"/>}
            </xsl:when>
            <xsl:otherwise>
                <xsl:value-of select="normalize-space(substring-before($text, $separator))"/>
                <xsl:call-template name="tokenize">
                    {<xsl:with-param name="text" select="substring-after($text, $separator)"/>}
                </xsl:call-template>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>
</xsl:stylesheet>

[]
{}
{}

使用XSLT 1.0精确获取输出有点棘手,但您可以使用您尝试过的mecanism。下面是一个XSLT 1.0,它使用缩进输出:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output method="text"/>
    <xsl:strip-space elements="*"/>
    <xsl:template match="Meta">
        <xsl:apply-templates/>
    </xsl:template>
    <xsl:template match="*">
        <xsl:param name="depth" select="0"/>
        <xsl:choose>
            <xsl:when test="$depth > 0">
                <xsl:text>&#10;</xsl:text>            
                <xsl:call-template name="addSpace">
                    <xsl:with-param name="nb" select="$depth"></xsl:with-param>
                </xsl:call-template>                
            </xsl:when>
            <xsl:when test="position() > 1">
                <xsl:text>&#10;</xsl:text>                            
            </xsl:when>
        </xsl:choose>        
        <xsl:choose>
            <xsl:when test="count(*) > 0">
                <xsl:text>[</xsl:text>
                <xsl:value-of select="local-name()"/>
                <xsl:text>]</xsl:text>                
            </xsl:when>
            <xsl:otherwise>
                <xsl:value-of select="local-name()"/>
            </xsl:otherwise>
        </xsl:choose>
        <xsl:apply-templates select="@syn|*">
            <xsl:with-param name="depth" select="$depth + 1"/>
        </xsl:apply-templates>       
    </xsl:template>
    <xsl:template name="tokenize" match="@syn">
        <xsl:param name="text" select="."/>
        <xsl:param name="depth" select="1"/>
        <xsl:param name="separator" select="','"/>
        <xsl:text>&#10;</xsl:text>
        <xsl:call-template name="addSpace">
            <xsl:with-param name="nb" select="$depth"></xsl:with-param>
        </xsl:call-template>
        <xsl:choose>
            <xsl:when test="not(contains($text, $separator))">
                <xsl:text>{</xsl:text>
                <xsl:value-of select="normalize-space($text)"/>
                <xsl:text>}</xsl:text>
            </xsl:when>
            <xsl:otherwise>
                <xsl:text>{</xsl:text>
                <xsl:value-of select="normalize-space(substring-before($text, $separator))"/>
                <xsl:text>}</xsl:text>
                <xsl:call-template name="tokenize">
                    <xsl:with-param name="text" select="substring-after($text, $separator)"/>
                    <xsl:with-param name="separator" select="$separator"/>
                    <xsl:with-param name="depth" select="$depth"/>
                </xsl:call-template>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>
    <xsl:template name="addSpace">
        <xsl:param name="nb"/>
        <xsl:text> </xsl:text>
        <xsl:if test="$nb >1 ">
            <xsl:call-template name="addSpace">
                <xsl:with-param name="nb" select="$nb - 1"></xsl:with-param>
            </xsl:call-template>            
        </xsl:if>
    </xsl:template>
</xsl:stylesheet>

请注意您的输出的差异:
元素位于括号之间,因为它有一个或多个子元素。

您几乎就在那里,只是在错误的东西周围放了括号,导致了错误

<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output method="text" indent="yes"/>
    <xsl:template match="/Meta"><xsl:apply-templates/></xsl:template>
    <xsl:template match="child::*"><xsl:call-template name="master"/><xsl:apply-templates/></xsl:template>
    <xsl:template name="master">
        <xsl:choose>
            <xsl:when test="count(child::*) = 0">
                <xsl:value-of select="local-name()"/>
                <xsl:apply-templates select="@syn"/>
            </xsl:when>
            <xsl:otherwise>
                [<xsl:value-of select="local-name()"/>]
                <xsl:apply-templates select="@syn"/>
        </xsl:otherwise>
        </xsl:choose>
    </xsl:template>
    <xsl:template name="tokenize" match="@syn">
        <xsl:param name="text" select="."/>
        <xsl:param name="separator" select="','"/>        
        <xsl:choose>
            <xsl:when test="not(contains($text, $separator))">
                {<xsl:value-of select="normalize-space($text)"/>}
            </xsl:when>
            <xsl:otherwise>
                {<xsl:value-of select="normalize-space(substring-before($text, $separator))"/>}
                <xsl:call-template name="tokenize">
                    <xsl:with-param name="text" select="substring-after($text, $separator)"/>
                </xsl:call-template>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>
</xsl:stylesheet>

[]
{}
{}

我会这样做:

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

  <xsl:output method="text"/>

  <xsl:param name="lf" select="'&#10;'"/>
  <xsl:param name="start-indent" select="'    '"/>
  <xsl:param name="br1" select="'['"/>
  <xsl:param name="br2" select="']'"/>
  <xsl:param name="br3" select="'{'"/>
  <xsl:param name="br4" select="'}'"/>
  <xsl:param name="sep" select="','"/>

  <xsl:template match="/Meta" priority="10">
    <xsl:apply-templates select="*">
      <xsl:with-param name="indent" select="''"/>
    </xsl:apply-templates>
  </xsl:template>

  <xsl:template match="*[not(*)]">
    <xsl:param name="indent"/>
    <xsl:value-of select="concat($indent, local-name(), $lf)"/>
    <xsl:apply-templates select="@syn">
      <xsl:with-param name="indent" select="concat($indent, $start-indent)"/>
    </xsl:apply-templates>
  </xsl:template>

  <xsl:template match="*[*]">
    <xsl:param name="indent"/>
    <xsl:value-of select="concat($indent, $br1, local-name(), $br2, $lf)"/>
    <xsl:apply-templates select="*">
      <xsl:with-param name="indent" select="concat($indent, $start-indent)"/>
    </xsl:apply-templates>
  </xsl:template>

  <xsl:template match="@syn">
    <xsl:param name="indent"/>
    <xsl:param name="text" select="."/>
    <xsl:choose>
      <xsl:when test="not(contains($text, $sep))">
        <xsl:if test="normalize-space($text)">
          <xsl:value-of select="concat($indent, $br3, normalize-space($text), $br4, $lf)"/>
        </xsl:if>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="concat($indent, $br3, normalize-space(substring-before($text, $sep)), $br4, $lf)"/>
        <xsl:apply-templates select=".">
          <xsl:with-param name="indent" select="$indent"/>
          <xsl:with-param name="text" select="substring-after($text, $sep)"/>
        </xsl:apply-templates>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

</xsl:stylesheet>


就像你在这里所做的那样。它很好地给出了结果。除了我添加一些这样的节点外:
如果您运行它,您会注意到Test1节点没有在正确的行上启动。我现在正在研究这个问题。Daktari,考虑编辑你的问题,向我们展示额外的输入文档,假设它由评论不显示的几行组成。@达克塔里:我更新了XSLT来考虑你的评论。正如马丁所指出的:也许你应该在你的问题中添加这个新的XML输入。@Vincent Biragnet非常感谢你——这正是我想要的结果。是的,XSLT1.0要复杂得多。我已经更新了问题。是的,我在发布后不久就意识到了这一点。然后注意到还有一些问题。谢天谢地,现在一切都解决了。谢谢马丁。你也采取了一种有趣的方法。Vincent Biragnet的代码为我做了这项工作,但我正在仔细查看您的代码,以便从中学习。谢谢你抽出时间。
[Subject]
 [People]
  Jane_Doe
   {janie}
   {jd}
  John_Doe
 [Object]
  [Table]
   Leg
  Chair
   {seat}
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output method="text" indent="yes"/>
    <xsl:template match="/Meta"><xsl:apply-templates/></xsl:template>
    <xsl:template match="child::*"><xsl:call-template name="master"/><xsl:apply-templates/></xsl:template>
    <xsl:template name="master">
        <xsl:choose>
            <xsl:when test="count(child::*) = 0">
                <xsl:value-of select="local-name()"/>
                <xsl:apply-templates select="@syn"/>
            </xsl:when>
            <xsl:otherwise>
                [<xsl:value-of select="local-name()"/>]
                <xsl:apply-templates select="@syn"/>
        </xsl:otherwise>
        </xsl:choose>
    </xsl:template>
    <xsl:template name="tokenize" match="@syn">
        <xsl:param name="text" select="."/>
        <xsl:param name="separator" select="','"/>        
        <xsl:choose>
            <xsl:when test="not(contains($text, $separator))">
                {<xsl:value-of select="normalize-space($text)"/>}
            </xsl:when>
            <xsl:otherwise>
                {<xsl:value-of select="normalize-space(substring-before($text, $separator))"/>}
                <xsl:call-template name="tokenize">
                    <xsl:with-param name="text" select="substring-after($text, $separator)"/>
                </xsl:call-template>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>
</xsl:stylesheet>
<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  version="1.0">

  <xsl:output method="text"/>

  <xsl:param name="lf" select="'&#10;'"/>
  <xsl:param name="start-indent" select="'    '"/>
  <xsl:param name="br1" select="'['"/>
  <xsl:param name="br2" select="']'"/>
  <xsl:param name="br3" select="'{'"/>
  <xsl:param name="br4" select="'}'"/>
  <xsl:param name="sep" select="','"/>

  <xsl:template match="/Meta" priority="10">
    <xsl:apply-templates select="*">
      <xsl:with-param name="indent" select="''"/>
    </xsl:apply-templates>
  </xsl:template>

  <xsl:template match="*[not(*)]">
    <xsl:param name="indent"/>
    <xsl:value-of select="concat($indent, local-name(), $lf)"/>
    <xsl:apply-templates select="@syn">
      <xsl:with-param name="indent" select="concat($indent, $start-indent)"/>
    </xsl:apply-templates>
  </xsl:template>

  <xsl:template match="*[*]">
    <xsl:param name="indent"/>
    <xsl:value-of select="concat($indent, $br1, local-name(), $br2, $lf)"/>
    <xsl:apply-templates select="*">
      <xsl:with-param name="indent" select="concat($indent, $start-indent)"/>
    </xsl:apply-templates>
  </xsl:template>

  <xsl:template match="@syn">
    <xsl:param name="indent"/>
    <xsl:param name="text" select="."/>
    <xsl:choose>
      <xsl:when test="not(contains($text, $sep))">
        <xsl:if test="normalize-space($text)">
          <xsl:value-of select="concat($indent, $br3, normalize-space($text), $br4, $lf)"/>
        </xsl:if>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="concat($indent, $br3, normalize-space(substring-before($text, $sep)), $br4, $lf)"/>
        <xsl:apply-templates select=".">
          <xsl:with-param name="indent" select="$indent"/>
          <xsl:with-param name="text" select="substring-after($text, $sep)"/>
        </xsl:apply-templates>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

</xsl:stylesheet>