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
使用XSL打印XML树_Xml_Xslt_Tree_Xmlnode_Xmlspy - Fatal编程技术网

使用XSL打印XML树

使用XSL打印XML树,xml,xslt,tree,xmlnode,xmlspy,Xml,Xslt,Tree,Xmlnode,Xmlspy,我有以下XML <?xml version="1.0" encoding="ISO-8859-1"?> <?xml-stylesheet type='text/xsl' href='parser.xsl'?> <NVS> <A> <F>007</F> </A> <A>-002</A> <B>--003</B>

我有以下XML

<?xml version="1.0" encoding="ISO-8859-1"?>
<?xml-stylesheet type='text/xsl' href='parser.xsl'?>
<NVS>
    <A>
        <F>007</F>
    </A>
    <A>-002</A>
    <B>--003</B>
    <C>
        <D>------005</D>
    </C>
    <E>-006</E>
</NVS>
我尝试了一些XSL,但没有得到正确的结果。 最好的XSL是:

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="html" encoding="ISO-8859-1" doctype-public="-//W3C//DTD XHTML//EN" doctype-system="http://www.w3.org/TR/2001/REC-xhtml11-20010531" indent="yes"/>
    <xsl:template match="/*">
        <html>
            <body>
                <xsl:for-each select=".">/<xsl:value-of select="."/>
                    <br/>
                </xsl:for-each>
            </body>
        </html>
    </xsl:template>
</xsl:stylesheet>

/

我还尝试了“针对每个人”,例如:

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="html" encoding="ISO-8859-1" doctype-public="-//W3C//DTD XHTML//EN" doctype-system="http://www.w3.org/TR/2001/REC-xhtml11-20010531" indent="yes"/>
    <xsl:template match="/*/*">
        <xsl:for-each select=".">/<xsl:value-of select="."/>
        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

/
但不是更好。而且我只需要输入值,而我只需要节点的名称


有什么想法吗?

一个可能的解决方案是遍历树并在运行时跟踪适当的输出。例如,当此XSLT:

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

  <xsl:template match="/*">
    <xsl:apply-templates mode="children">
      <xsl:with-param name="pName" select="name()"/>
    </xsl:apply-templates>
  </xsl:template>

  <xsl:template match="*[*]" mode="children">
    <xsl:param name="pName"/>
    <xsl:variable name="vNewName" select="concat($pName, '/', name())"/>
    <xsl:value-of select="concat('/', $vNewName, '/&#10;')"/>
    <xsl:apply-templates mode="children">
      <xsl:with-param name="pName" select="$vNewName"/>
    </xsl:apply-templates>
  </xsl:template>

  <xsl:template match="*[not(*)]" mode="children">
    <xsl:param name="pName"/>
    <xsl:value-of select="concat('/', $pName, '/', name(), '/&#10;')"/>
  </xsl:template>

</xsl:stylesheet>
说明:

  • 模板#1匹配根节点,并指示处理器将模板应用于其所有子节点,同时单独传递一个
    $pName
    参数,该参数目前包含根节点的名称。注意使用
    mode=“children”
    ;我使用此选项,以便将来具有更通用匹配的模板不包括此根节点
  • 模板#2匹配所有具有子节点(并且正在使用
    mode=“children”
    )的节点。在找到这样一个节点后,处理器输出一行文本,该行文本将携带的
    $pName
    参数、正斜杠和当前元素的名称组合在一起。最后,模板通过将模板应用于所有子节点并传递一个参数来模仿模板#1——不过,这次,该参数包含在该节点之前创建并包含该节点的连接文本
  • 模板#3匹配所有没有子节点(并且再次使用
    mode=“children”
    )的节点。一旦找到这样一个节点,处理器就会输出一行与模板#2相当类似的文本

另一个选项是使用
祖先轴或self
轴返回树

XML输入

<NVS>
    <A>
        <F>007</F>
    </A>
    <A>-002</A>
    <B>--003</B>
    <C>
        <D>------005</D>
    </C>
    <E>-006</E>
</NVS>
/NVS
/NVS/A
/NVS/A/F
/NVS/A
/NVS/B
/NVS/C
/NVS/C/D
/NVS/E
当元素在给定级别上多次存在时,您还可以通过在谓词中添加位置来轻松地修改它以提供精确的路径。例如,有两个
A
元素是
/NVS
的子元素

XSLT1.0

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="text"/>
    <xsl:strip-space elements="*"/>

    <xsl:template match="text()"/>

    <xsl:template match="*">
        <xsl:for-each select="ancestor-or-self::*">
            <xsl:value-of select="concat('/',local-name())"/>
        </xsl:for-each>
        <xsl:text>&#xA;</xsl:text>
        <xsl:apply-templates select="node()"/>
    </xsl:template>

</xsl:stylesheet>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="text"/>
    <xsl:strip-space elements="*"/>

    <xsl:template match="text()"/>

    <xsl:template match="*">
        <xsl:for-each select="ancestor-or-self::*">
            <xsl:value-of select="concat('/',local-name())"/>
            <xsl:if test="(preceding-sibling::*|following-sibling::*)[local-name()=local-name(current())]">
                <xsl:value-of select="concat('[',count(preceding-sibling::*[local-name()=local-name(current())])+1,']')"/>
            </xsl:if>
        </xsl:for-each>
        <xsl:text>&#xA;</xsl:text>
        <xsl:apply-templates select="node()"/>
    </xsl:template>

</xsl:stylesheet>
此外,如果您不希望根元素输出的路径,只需添加以下模板:

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


处理属性也很容易。如果你想举个例子,请告诉我。是的!太好了,它工作得非常好。这正是我所期望的:简单、轻便、高效。当一个元素被多次使用时,我不需要显示它的位置,但是看看它是如何完成的很有趣。顺便问一下, ;需要什么@OranginaRouge-The
和#xA是一个换行符。如果没有它,所有的输出都将在一行上。感谢您快速而清晰的回答。你的解释对我帮助很大,因为最终它比我想象的要难一点。这也是我选择上面第二个更简单的解决方案的原因之一。
/NVS
/NVS/A
/NVS/A/F
/NVS/A
/NVS/B
/NVS/C
/NVS/C/D
/NVS/E
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="text"/>
    <xsl:strip-space elements="*"/>

    <xsl:template match="text()"/>

    <xsl:template match="*">
        <xsl:for-each select="ancestor-or-self::*">
            <xsl:value-of select="concat('/',local-name())"/>
            <xsl:if test="(preceding-sibling::*|following-sibling::*)[local-name()=local-name(current())]">
                <xsl:value-of select="concat('[',count(preceding-sibling::*[local-name()=local-name(current())])+1,']')"/>
            </xsl:if>
        </xsl:for-each>
        <xsl:text>&#xA;</xsl:text>
        <xsl:apply-templates select="node()"/>
    </xsl:template>

</xsl:stylesheet>
/NVS
/NVS/A[1]
/NVS/A[1]/F
/NVS/A[2]
/NVS/B
/NVS/C
/NVS/C/D
/NVS/E
<xsl:template match="/*">
    <xsl:apply-templates/>
</xsl:template>