【问题标题】:How to convert Xpath syntax to XSL/XSLT syntax?如何将 Xpath 语法转换为 XSL/XSLT 语法?
【发布时间】:2016-11-18 15:46:04
【问题描述】:

我了解 XPath 语法的工作原理,并且可以编写 Xpath 命令以从 XML 文件中提取某些信息。
我想将我的 XPath 命令转换为 XSLT 脚本,以便其他人可以通过 XML 文件运行脚本以获得相同的输出。

例如

我有一个 XML 文件,比如说,如下所示:

<?xml version="1.0" encoding="UTF-8"?>
  <library>
        <section id="109196796">
            <master_information>
                <shelf_identifier>
                    <identifier type="CodeX" type_id="2">LB1500605917</identifier>
                    <identifier type="Common Code" type_id="15">150060591</identifier>
                </shelf_identifier>
                <shelf_master>
                    <section_type>1</section_type>
                    <book_type>3</book_type>
                </shelf_master>
            </master_information>
        </section>
        <section id="109196798">
            <master_information>
                <shelf_identifier>
                    <identifier type="CodeX" type_id="2">LB0777775917</identifier>
                    <identifier type="Common Code" type_id="15">077777591</identifier>
                </shelf_identifier>
                <shelf_master>
                    <section_type>1</section_type>
                    <book_type>3</book_type>
                </shelf_master>
            </master_information>
        </section>
        <section id="109196800">
            <master_information>
                <shelf_identifier>
                    <identifier type="CodeX" type_id="2">LB2589165917</identifier>
                    <identifier type="Common Code" type_id="15">258916591</identifier>
                </shelf_identifier>
                <shelf_master>
                    <section_type>1</section_type>
                    <book_type>3</book_type>
                </shelf_master>
            </master_information>
        </section>
  </library>


如果我运行下面的 XPath 命令,

//identifier[@type='CodeX']

我得到了输出:

LB1500605917
LB0777775917
LB2589165917

..这是预期的。现在,我尝试将 XPath 命令转换为 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="text"/>
    <xsl:variable name="return">
    <xsl:text>
</xsl:text> <!-- defined a line break -->
    </xsl:variable>
    <xsl:template match="//library"></xsl:template>
    <xsl:template match="//section/master_information/shelf_identifier/identifier"> 
        <xsl:value-of select="@type='CodeX'"/>
        <xsl:value-of select="$return"/> <!-- this basically puts a line break -->
    </xsl:template>
</xsl:stylesheet>

XSL 似乎是正确的。但是,不会生成任何输出。

我是 XSL/XSLT 的新手。我究竟做错了什么?

【问题讨论】:

  • 您是否尝试过仅使用一个模板或在 value-of select 上指定 xpath??
  • 感谢您的回复。我尝试删除库模板并将第二个模板更改为“//标识符”我得到以下输出:true false 13true false 13true false 13 这没有意义,因为它们甚至不存在于文件中。
  • @Pernambuco - 如果您在 xsl:value-of 选择中使用相同的 XPath (//identifier[@type='CodeX']),并且您使用的是 XSLT 1.0,那么您只会获得第一个值。跨度>

标签: xml xslt xpath


【解决方案1】:

你可以做的是添加一个与你的 xpath 相同节点匹配的模板,然后输出值和换行符......

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="text"/>
  <!--The strip-space isn't completely necessary. I just always include it in my
  default stylesheets. It strips whitespace. You can preserve whitespace with
  xsl:preserve-space. See https://www.w3.org/TR/xslt#strip for more details.-->
  <xsl:strip-space elements="*"/>

  <!--Suppress output of text nodes by built-in templates.-->
  <xsl:template match="text()"/>

  <!--Match "indentifier" elements that contain a "type" attribute
  with the value of "CodeX".-->
  <xsl:template match="identifier[@type='CodeX']">
    <!--Output the value of the current context ("identifier") concatenated with
    a newline. ("&#xA;" is a hex entity reference. You could also use a decimal
    reference ("&#10;")). You could use either of these references as the value
    of a variable too (or even declare it as an entity).
    I use normalize-space() instead of . to clean up any additional spaces.
    See https://www.w3.org/TR/xpath/#function-normalize-space for details.-->
    <xsl:value-of select="concat(normalize-space(),'&#xA;')"/>
  </xsl:template>

</xsl:stylesheet>

注意匹配text() 的空模板。这是为了抑制 XSLT 的 built-in template rules 的 text() 节点的输出而添加的。

另外请注意,我在比赛中没有使用//。这也是因为内置规则;它们默认允许递归处理。

【讨论】:

  • 您好丹尼尔,非常感谢您的回复。你的剧本就像一个魅力!不过,我仍在尝试了解您所做的更改。如果问得不算多,您能否添加 cmets 简要说明您更改的每一行的作用?这将非常有帮助。我将研究内置的模板规则——这对我来说是新的。谢谢!
  • @Fenil - 当然没问题。我会在几分钟后编辑。
  • @丹尼尔再次感谢!
  • @Fenil - 我添加了一些 cmets。如果您仍有疑问,请告诉我。 “内置”链接将有助于理解 XSLT 的工作原理。谢谢!
【解决方案2】:

你为什么不简单地做:

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" encoding="UTF-8"/>

<xsl:template match="/">
    <xsl:for-each select="//identifier[@type='CodeX']">
        <xsl:value-of select="."/>
        <xsl:text>&#10;</xsl:text>
    </xsl:for-each>
</xsl:template>

</xsl:stylesheet>

【讨论】:

  • 你的脚本也可以!直到今天我才知道我们可以直接在选择字段中输入 Xpath 命令。很高兴知道。我已经接受了别人的回答。感谢您的回复!
  • “直到今天我才知道......” - 这样的话让我害怕。您是否只是通过查看其他人的代码自学了 XSLT?你就是这样学开车的吗?
  • @MichaelKay 哈哈,不。我被投入到 XSLT 中,并在学习过程中学习,但还没有以正式的方式学习它。我们并没有像学习其他东西那样真正学习一切,不是吗? :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-07-10
  • 2015-10-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多