【问题标题】:Generate XPath using XPath使用 XPath 生成 XPath
【发布时间】:2012-04-26 11:34:44
【问题描述】:

我有两种不同类型的 XML 文档(一种是 a.xml,另一种是 b.xml)。文档a.xml 是我的主要源文档,我必须在其上运行查询。文档b.xml 包含从a.xml 获取记录的所有可能信息。

文档:«a.xml»

<rs>
    <r id="r1">
        <f0>typeA</f0>
        <f1>contains value1, value2 and value3</f1>
    </r>
    <r id="r2">
        <f0>typeB</f0>
        <f1>contains value4 and value7</f1>
    </r>
    <r id="r3">
        <f0>typeA</f0>
        <f1>contains value2 and value5</f1>
    </r>
    <r id="r4">
        <f0>typeC</f0>
        <f1>contains value1 and value6</f1>
    </r>
    <r id="r5">
        <f0>typeA</f0>
        <f1>contains value5</f1>
    </r>
    <r id="r6">
        <f0>typeC</f0>
        <f1>contains value1, value2 and value3</f1>
    </r>
</rs>

文档:«b.xml»

<?xml version="1.0"?>
<qs>
    <q id="q1">
        <i0>typeA</i0>
        <i1>value1|value2|value3</i1>
        <i2>value18|value35</i2>
        <i3>value1|value7</i3>
    </q>
    <q id="q2">
        <i0>typeB</i0>
        <i1>value2|value7</i1>
        <i2>value9|value20</i2>
        <i3>value4</i3>
    </q>
</qs>

现在我想根据b.xml 的值生成动态XPath selector strings 以存储在文档c.xml 中。它看起来像:

文档c.xml

<xps>
    <xp id="q1">
        <t1>/rs/r[contains(f0,'typeA') 
                and contains(f1,'value1') 
                and contains(f1,'value2') 
                and contains(f1,'value3')]</t1>
        <t2>/rs/r[contains(f0,'typeA') 
                and contains(f1,'value18') 
                and contains(f1,'value35')]</t2>
        <t3>/rs/r[contains(f0,'typeA') 
                and contains(f1,'value1') 
                and contains(f1,'value7')]</t3>
    </xp>
    <xp id="q2">
        <t1>/rs/r[contains(f0,'typeB') 
                and contains(f1,'value2') 
                and contains(f1,'value7')]</t1>
        <t2>/rs/r[contains(f0,'typeA') 
                and contains(f1,'value9') 
                and contains(f1,'value20')]</t2>
        <t3>/rs/r[contains(f0,'typeA') 
                and contains(f1,'value4')]</t3>
    </xp>
</xps>

如果这里有人知道如何在 XSLT 1.0 版中完成这项工作。提前致谢。

【问题讨论】:

    标签: xslt xpath


    【解决方案1】:

    这是 XSLT 1.0 中的一个解决方案:

    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
        <xsl:output method="xml" encoding="utf-8" indent="yes"/>
    
        <xsl:template match="@*|text()" />
    
        <xsl:template match="/">
            <xps>
                <xsl:apply-templates/>
            </xps>
        </xsl:template>
    
        <xsl:template match="q">
            <xp id="{@id}">
                <xsl:apply-templates/>
            </xp>
        </xsl:template>
    
        <xsl:template match="*[starts-with(name(), 'i')][not(self::i0)]">
            <xsl:element name="t{substring-after(name(), 'i')}">
                <xsl:text>/rs/r[contains(f0, '</xsl:text>
                <xsl:value-of select="preceding-sibling::i0"/>
                <xsl:text>')</xsl:text>
                <xsl:call-template name="more-conditions">
                    <xsl:with-param name="list" select="."/>
                </xsl:call-template>
                <xsl:text>]</xsl:text>
            </xsl:element>
        </xsl:template>
    
        <xsl:template name="more-conditions">
            <xsl:param name="list"/>
            <xsl:param name="delimiter" select="'|'"/>
    
            <xsl:choose>
                <xsl:when test="contains($list, $delimiter)">
                    <xsl:call-template name="more-conditions">
                        <xsl:with-param name="list" select="substring-before($list, $delimiter)"/>
                    </xsl:call-template>
                    <xsl:call-template name="more-conditions">
                        <xsl:with-param name="list" select="substring-after($list, $delimiter)"/>
                    </xsl:call-template>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:text> and contains(f1, '</xsl:text>
                    <xsl:value-of select="$list"/>
                    <xsl:text>')</xsl:text>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:template>
    
    </xsl:stylesheet>
    

    应用于您的输入文档,它会产生以下输出:

    <xps>
        <xp id="q1">
            <t1>/rs/r[contains(f0, 'typeA') and contains(f1, 'value1') and contains(f1, 'value2') and contains(f1, 'value3')]</t1>
            <t2>/rs/r[contains(f0, 'typeA') and contains(f1, 'value18') and contains(f1, 'value35')]</t2>
            <t3>/rs/r[contains(f0, 'typeA') and contains(f1, 'value1') and contains(f1, 'value7')]</t3>
        </xp>
        <xp id="q2">
            <t1>/rs/r[contains(f0, 'typeB') and contains(f1, 'value2') and contains(f1, 'value7')]</t1>
            <t2>/rs/r[contains(f0, 'typeB') and contains(f1, 'value9') and contains(f1, 'value20')]</t2>
            <t3>/rs/r[contains(f0, 'typeB') and contains(f1, 'value4')]</t3>
        </xp>
    </xps>
    

    我添加了一些空格。您可以根据需要修改转换,但这应该可以帮助您入门。

    【讨论】:

      【解决方案2】:

      在 xslt 版本 1 中,您不能将变量用作 xpath 选择器,但是您可能有其他方法可以完成此任务。如果您提供问题的想法而不是您的预期解决方案,人们可​​能会提供帮助:)

      【讨论】:

      • 我只想生成c.xml,稍后,基于该文件,将创建另一个 XSL 文件。但是,我只需要生成c.xml
      猜你喜欢
      • 2022-12-18
      • 1970-01-01
      • 2016-11-30
      • 1970-01-01
      • 1970-01-01
      • 2014-01-18
      • 2011-07-10
      • 1970-01-01
      • 2013-09-18
      相关资源
      最近更新 更多