【问题标题】:XPath to find straddle rows in CALS modelXPath 在 CALS 模型中查找跨行
【发布时间】:2014-02-25 09:34:51
【问题描述】:

我正在构建一个流程来遍历大量 XML 文件,查找 CALS 模型表(大多数文件至少包含一个),然后将表格数据存储回数据库。在第一种情况下,这些表中的许多表会有不同的结构,但我想使用数据库来分析结构的共性。我在下面列出了来自示例文件的(不完整的)摘录。

   <table frame="none">
        <tgroup cols="6" colsep="0" rowsep="0">
            <colspec colname="1" colnum="1" colwidth="127pt" align="center"/>
            <colspec colname="2" colnum="2" colwidth="39pt" align="center"/>
            <colspec colname="3" colnum="3" colwidth="30pt" align="center"/>
            <colspec colname="4" colnum="4" colwidth="33pt" align="center"/>
            <colspec colname="5" colnum="5" colwidth="33pt" align="center"/>
            <colspec colname="6" colnum="6" colwidth="87pt"/>
            <thead>
                <row valign="bottom">
                    <entry align="center">Product</entry>
                    <entry>SKU</entry>
                    <entry>Length</entry>
                    <entry>Depth</entry>
                    <entry align="center">Weight</entry>
                    <entry align="center">Remarks</entry>
                </row>
                <row valign="bottom">
                    <entry></entry>
                    <entry></entry>
                    <entry>(m)</entry>
                    <entry>(m)</entry>
                    <entry align="center">(kg) </entry>
                    <entry align="center"> </entry>
                </row>
            </thead>
            <tbody>
                <row>
                    <entry align="left" namest="1" nameend="6"><hd4>Whites</hd4></entry>
                </row>
                <row>
                    <entry>Albion</entry>
                    <entry>12345</entry>
                    <entry>398</entry>
                    <entry>15.5</entry>
                    <entry> </entry>
                    <entry>N/A </entry>
                </row>
                <row>
                    <entry>Rotorua</entry>
                    <entry>12346</entry>
                    <entry>398</entry>
                    <entry>15.5</entry>
                    <entry> </entry>
                    <entry> </entry>
                </row>
                <row>
                    <entry>Quintep</entry>
                    <entry>12347</entry>
                    <entry>398</entry>
                    <entry>15.5</entry>
                    <entry> </entry>
                    <entry> </entry>
                </row>

由于我知道在此过程中会遇到不同的结构,我无法在数据库中创建一个表架构来保存所有这些数据,只能将其存储为具有以下属性的实体:

  • doc_id
  • table_id
  • row_id
  • col_id
  • col_name
  • col_units
  • entry_value

这将允许我将字符串和数值存储为字符串。

在某些情况下需要的附加属性是上面示例中跨行行中定义的“类别”,位于 tbody/row[1]。在这里,原始文档创建者添加了一个跨越来对紧随其后的行进行分类:

<row>
    <entry align="left" namest="1" nameend="6"><hd4>Whites</hd4></entry>
</row>

这些跨行给我带来了一些困难。在它们出现的地方,它们对直到下一个跨越发生之后的行进行“分类”。

我最初的文档分析表明,与这些跨式相关的表结构有多种可能的“类型”:

  • 类型 1。表格中不出现跨式 - 简单且易于处理
  • 类型 2。tbody 中的第一行是跨式,并且在 tbody 下方有零个或多个进一步的跨式
  • 类型 3。表格包含跨接但不在 tbody 的第一行

类型 3 '可以' 被视为 2 个单独的表,一个类型 1(直到第一个跨行但不包括所有行)和一个类型 2(从第一个跨行向前的所有行)

所以看来解决这个处理问题的关键是确定第一个跨接的位置,将跨接之前的所有内容(零行或多行)视为Type1,并将跨接前的所有内容视为Type 2。

但我在确定第一个跨骑的位置时遇到了一些困难。我对 1st straddle 的定义——用 Xpath 术语来说——是

tbody/row[entry [@nameend &gt; @namest]][1]

这允许跨式并不总是从第 1 列键入,并且并不总是延伸到最后一列。这两种可能性都存在于现实世界的数据中。

所以我的问题仍然回到确定第一个跨骑的位置。

此页面上列出了许多类似的解决方案 http://www.dpawson.co.uk/xsl/sect2/flatfile.html#d5010e13

但我很难将它们应用到我的实例中。

这样的事情可能会奏效

<xsl:key name="straddles" match="row[entry[@nameend &gt; @namest]]" use="entry/@namest"/>

但我不确定使用什么来定义键的@use 属性?

当我尝试定义第一跨变量时,我没有定义值可传递给 key() 函数?

<xsl:variable name="first-straddle" select="table/tgroup/tbody/row[generate-id() = generate-id(key('straddles',?????))]"/>

如何找到第一个跨骑的位置?

提前致谢

附加说明: ![在浏览器中呈现的示例表的屏幕截图]https://dl.dropboxusercontent.com/u/5065004/Screen%20Shot%202014-02-25%20at%2013.54.08.png 上面的屏幕截图显示了在浏览器中呈现的示例表。跨行对以下行中的数据进行“分类” - 一直到下一个跨行。 @nasmest 和@nameend 属性定义了被标题跨越的列数,而不是下一个跨越之前的行数。后一个值是标记中的 IMPLICIT 并且是我正在搜索的 XPath 语句。前者 - 跨列 - 在标记中是明确的。

【问题讨论】:

  • 您所指的“跨界”等于 html 表格中的colspan。你需要考虑另一个属性morerows,它相当于html表中的rowspan
  • Joel - 在我正在分析的数据集合中的任何地方都没有使用 morerows 属性。我需要四处插入它。为此,我需要知道在哪里插入它。鸡和蛋,我想。

标签: xslt xpath xslkey


【解决方案1】:

如果我按照这个正确(大IF),每个&lt;entry&gt;可以通过查看找到其对应的类别:

<xsl:value-of select="parent::row/preceding-sibling::row[entry[@namest]][1]/entry/hd4"/>

[编辑 ----------------------------------
澄清一下:这是从entry 的上下文中调用的。阅读如下:
1.上去家长row;
2. 在具有entry 且具有namest 属性的同一父tbody向后查找最近的row
3.获取步骤2中找到的rowentryhd4元素的值。
------------------ ------------------------- ]

但是,这似乎还不够; &lt;entry&gt; 还需要检查其在父行中的位置是否在 namest 和 nameend 属性设置的范围内?如果这是正确的,那么它提出了另一个问题:是否有可能有两个共存的“跨界”?例如,第 1 到 3 列的一个类别,第 5 到 6 列的另一个类别?


编辑

请检查以下示例:

<tbody>
    <row>
        <entry namest="1" nameend="3"><hd4>Colors</hd4></entry>
    </row>
    <row>
        <entry>Red</entry>
        <entry>Green</entry>
        <entry>Blue</entry>
    </row>
    <row>
        <entry>Black</entry>
        <entry>White</entry>
    </row>
    <row>
        <entry>Cyan</entry>
        <entry>Magenta</entry>
        <entry>Yellow</entry>
        <entry>Widget(not a color)</entry>
    </row>
    <row>
        <entry namest="4" nameend="5"><hd4>Shapes</hd4></entry>
    </row>
    <row>
        <entry>Brown</entry>
        <entry>Pink</entry>
        <entry>Golden</entry>
        <entry>Circle</entry>
    </row>
    <row>
        <entry>Azure</entry>
        <entry>Grey</entry>
        <entry>Orange</entry>
        <entry>Square</entry>
        <entry>Triangle</entry>
        <entry>Gadget(neither a color nor a shape)</entry>
    </row>
</tbody>

如果我理解正确,第二个“跨越”不会取代第一个,而是补充。因此,如果我们现在尝试从以下上下文应用上述 xPath:

<entry>Pink</entry>

我们会得到错误的结果(形状),因为我们查找了前面的第一个“跨越” - 而我们应该查找了适用于列 # 的前面的第一个“跨越” 2.

【讨论】:

  • 是的。正如您所描述的,单行可以有 2 个跨骑。
  • 是的。正如您所描述的,单行可以有 2 个跨式。但我不确定这是一个大问题。 ANY straddle 的存在将一行描述为“类别”行。因此,在定义要使用的行时,2 个跨接的存在与仅一个跨接一样好。我对使用多个“::”轴有点不清楚。您能否详细说明 XPath 的读取方式?我假设它是从右到左读的? parent::row/preceding-sibling::row 指的是什么? B4 有问题的行出现的行的父元素?不确定 parent:: 是否必要?
  • @Feargal 1. 我已对我的回答进行了澄清。 2. 我不确定您是否理解我对将两个“跨越”应用于单行的担忧 - 我添加了一个示例来说明。
  • 我已经更新了我原来的问题并添加了一个截图(虽然它目前只是链接 - 仍然得到降价的窍门) - 你有一点错误的一端。 nameend 和 namest 的值与决定哪个跨行行应用于当前数据行无关。无论 namest 或 nameend 的值如何,它总是最接近的前跨。跨式不需要“覆盖”有问题的列。这有意义吗?
  • @Feargal "nameend 和namest 的值在决定哪个跨行行应用于当前数据行时无关紧要。无论namest 或nameend 的值如何,它始终是最接近的前跨。 “我不相信一般情况下是这样 - 但如果在你的情况下总是如此,那么我的第一个答案应该对你有用。
猜你喜欢
  • 2021-10-26
  • 1970-01-01
  • 1970-01-01
  • 2013-09-21
  • 1970-01-01
  • 1970-01-01
  • 2018-09-23
  • 2010-09-13
  • 2021-12-17
相关资源
最近更新 更多