问题描述
我有一个像下面这样的 xml,我正在尝试将 xml 转换为 csv
<module>
<content>
<catalouge SC="25" item="200">
<Number id="250" RefIds="xyz20000">
<Character condValue="PRE">
<count Number="1" Name="Sree" changeMark="1">FOR A/C 0013,0047,0063</count>
</Character>
<Character condValue="EMB">
<count Number="154" Name="Sree" changeMark="1">FOR A/C 0005-0010,0021,0025,0033</count>
</Character>
</Number>
</catalouge>
<catalouge SC="180" item="200" >
<Number id="780" RefIds="xyz20000">
<Character condValue="EMB">
<count Number="1" Name="AB">FOR A/C 0006-0011</count>
</Character>
<Character condValue="EMB">
<count Number="154" Name="Sree" changeMark="1">FOR A/C 0013</count>
</Character>
</Number>
</catalouge>
<catalouge SC="567" item="240">
<Number id="666" Value="123" RefIds="xyz20000">
<Character condValue="EMB">
<count Number="2" Name="SB">FOR A/C 0008-0013</count>
</Character>
<Character condValue="PRE">
<count Number="1" Name="cherry" changeMark="1">FOR A/C 0018,0063</count>
</Character>
</Number>
</catalouge>
<catalouge SC="8" item="280">
<Number id="1994" Value="1234" RefIds="xyz20000" >
<Character condValue="POST">
<count Number="3" Name="Sree" changeMark="1">FOR A/C 0006,0063,0090,0143,0172</count>
</Character>
</Number>
</catalouge>
</content>
</module>
我的xquery如下
for $p in doc("dar.xml")//module/content/catalouge
let $SC := $p/string(@SC)
let $item := $p/string(@item)
let $isns := $p/Number
for $isn in $isns
let $id := $isn/string(@id)
let $Ref := $isn/string(@RefIds)
let $chr := (for $x in $isn return string-join($x//Character//@condValue,","))
let $chr_status := contains($chr,'EMB')
**let $count := $isn/Character/data(count)
let $count_status := contains($chr,'0006')**
let $Num := $isn/Character/count/string(@Number)
let $sep :=";"
return (if($chr_status and $count_status)
then ()
else(concat($SC,$sep,$item,$id,$Ref))
)
我在这里执行 and 操作,如果两个状态都为真,则不打印任何内容,如果为假,则应打印一些值。 我的输出应该如下:
567;240;666;xyz20000
8;280;1994;xyz20000
但这里我的问题是,计数标记中存在的数据具有一系列值,如何增加范围标记这些值并搜索返回布尔值的 0006
<count Number="154" Name="Sree" changeMark="1">FOR A/C 0005-0012,0033</count>
对于 A/C 0005-0012,0033 这实际上意味着 0005 到 0012--> 我有序列 0005,0006,0007,0008,0009,0010,00211,0033
任何想法将不胜感激,谢谢!
解决方法
标记一个逗号分隔的字符串并搜索一个成员,在匹配的情况下返回一个布尔值:
appendComponentToBody
,
这似乎与您之前的问题类似,您可以在删除 tokenize
前缀后使用 to
和 FOR A/C
运算符:
//count
!
(.
|| ': '
|| (((
substring-after(.,'FOR A/C ') !
tokenize(.,',') !
(let $tokens := tokenize(.,'-')!xs:integer(.)
return
(
if ($tokens[2])
then ($tokens[1] to $tokens[2])
else $tokens[1])
)
! format-integer(.,'0001')) = '0006')))
https://xqueryfiddle.liberty-development.net/94hwpi2/2 给予
FOR A/C 0013,0047,0063: false
FOR A/C 0005-0010,0021,0025,0033: true
FOR A/C 0006-0011: true
FOR A/C 0013: false
FOR A/C 0008-0013: false
FOR A/C 0018,0063: false
FOR A/C 0006,0063,0090,0143,0172: true
,
使用这个纯 XPath 2.0 表达式:
for $text in 'FOR A/C 0005-0010,0033'
return
(for $vTokens in tokenize(substring-after($text,'FOR A/C '),'\s*,\s*')
return
$vTokens = '0006'
or
$vTokens[for $part1 in tokenize(.,'-')[1],$part2 in tokenize(.,'-')[2]
return
$part1 le '0006' and $part2 ge '0006'
]
)[.] and true()
这应该计算为 true()
。
这是一个多输入的例子:
for $text in
('FOR A/C 0013,0063','FOR A/C 0005-0010,0033','FOR A/C 0006-0011','FOR A/C 0013','FOR A/C 0008-0013','FOR A/C 0018,'FOR A/C 0006,0172')
return
(for $vTokens in tokenize(substring-after($text,'-')[2]
return
$part1 le '0006' and $part2 ge '0006'
]
)[.] and true()
评估后,再次产生正确的结果:
false true true false false false true