【问题标题】:XSLT check if String is inside a setXSLT 检查字符串是否在集合内
【发布时间】:2016-07-01 19:28:58
【问题描述】:

我正在尝试检查字符串是否包含在集合中。我有一张 Excel 表格,我将其转换为 xml 文件;示例:

左侧是 Excel 工作表,右侧是转换后的工作表 (RowData.xml):

所以我有一个xml 文件,其中这些数字可能存在也可能不存在。例如,源 xml 可能如下所示:

Source.xml:

<Data>
    <Number>5556781234</Number>
    <Number>5556781235</Number>
    <Number>5556781236</Number>
</Data>

如您所见,它可以在任何地方停止。源 xml 文件可能包含 RowData.xml 中列出的所有数字,也可能只有 1 个或多个。所以我的问题是,如何在我的 xslt 文件中检查它?

我想这样做:

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

<!-- This is the Excel sheet converted to an XML file -->
<xsl:param name="sheet-uri" select="'RowData.xml'"/>
<xsl:param name="sheet-doc" select="document($sheet-uri)"/>

<xsl:template match="Data">
    <xsl:for-each select="Data/Number">
        <xsl:variable name="continue" select="$sheet-doc//Sheet/Row[Number = current()]/Continue"/>

        <xsl:if test="">
            <!-- Check the Source.xml against the RowData.xml and 
                 see if the set contains any "No"'s in it. -->

            <!-- If it does then don't do the following -->

            <Data2>
                <Number><xsl:value-of select="Number"/></Number>
                <Timestamp>125222</Timestamp>
            </Data2>
        </xsl:if>
    </xsl:for-each>
</xsl:template>

所以基本上,在创建&lt;Data2&gt; 元素之前,检查Source.xml 中的数字,看看这些数字中的任何一个对于RowData.xml 中的Continue 列的值是否为No。我不知道如何制作上面的if 声明。我知道xslt 中有一个contains() 函数;但是,我不知道如何在这里使用它。

这可能吗?如果有什么令人困惑的地方,请告诉我。提前致谢!

【问题讨论】:

    标签: java xml excel xslt saxon


    【解决方案1】:

    检查 Source.xml 中的数字,看看这些数字中是否有任何数字对于 RowData.xml 中的 Continue 列的值为 No。

    您可以在这里利用 XSLT 的“存在​​相等”运算符:

    test="doc('source.xml')/Data/Number = 
        $sheet-doc//Sheet/Row[Continue='No']/Number"
    

    本质上,如果 A 和 B 是一组值,那么如果 A 中的某个值等于 B 中的某个值,则 A = B 返回 true。

    【讨论】:

    • 感谢您的回复,这个好像可以了!但是,有没有另一种写法doc('source.xml')/Data/Number?在我的 Java 代码中,我将文件转换为字符串并使用Document 类对其进行解析,然后通过将其作为DOMSource(document) 传递来进行转换。例如,this 函数会很棒。
    • 如果唯一的原因是运行 XSLT 转换,您真的不想创建 DOM。使用 Saxon,转换 DOM 的时间是使用 Saxon 自己的原生树模型的 5-10 倍。尝试切换到 s9api 接口并使用 DocumentBuilder 创建树,然后将其作为样式表参数传入。
    • 我切换到 s9api 但上面的 test 语句不断返回 false (这与我的旧代码相同)。我通过 Java 代码使用文档的文件路径设置参数。我在声明中唯一更改的是开头部分:doc($source-xml)...。参数名称为$source-xml。我做错了什么?
    • 抱歉,当您使用的是一些不同的代码和对您所做更改的描述时,很难调试代码。要找出你做错了什么,我需要确切地看看你做了什么。
    • 哦,我想通了。这是一个简单的错字。谢谢大家的帮助!
    【解决方案2】:

    我建议你使用 key 机制 - 尤其是。如果您使用的是 XSLT 2.0。

    定义一个键为:

    <xsl:key name="row" match="Row" use="Number" />
    

    然后做:

    <xsl:template match="/Data">
        <xsl:for-each select="Number[not(key('row', ., $sheet-doc))]">
            <Data2>
                <xsl:copy-of select="."/>
                <Timestamp>125222</Timestamp>
            </Data2>
        </xsl:for-each>
    </xsl:template>
    

    这只会选择在RowData.xml 文档中没有对应RowNumber元素。

    【讨论】:

    • 我不太明白你的最后一句话。如果我按照Source.xml 给出的示例,for-each 语句将只选择与RowData.xml 中的数字匹配的&lt;Row&gt; 标记?
    • 不,它会选择所有其他人。那是因为您的评论说“如果确实如此,则不要执行以下操作”。我的代码说:如果没有,请执行以下操作
    • 哦,好的。如果我取出not,那么我会得到与Source.xml 中的数字匹配的所有数字?从那里,我可以检查该集合是否有任何 Continue 等于 No
    • 类似这样的东西:Number[(key('row', ., $sheet-doc))]/Continue = 'No'?
    • 如果您只想匹配 Continue = No 的行,您可以将关键字缩小到:&lt;xsl:key name="row" match="Row[Continue = 'No']" use="Number" /&gt;。 -- 我认为你的版本也应该可以工作。
    猜你喜欢
    • 2010-10-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-19
    • 2018-08-27
    相关资源
    最近更新 更多