【发布时间】:2014-11-10 17:47:41
【问题描述】:
在我当前的 XML 文档中,有一些特定的、特定的原子文本,需要在其周围包装一个新元素。
这是我当前 XML 的 sn-p:
<html n1="namespace1" n2="namespace2">
<head>
<title>Document Title</title>
</head>
<body>
THIS IS UNTAGGED TEXT
<n1:a>
<n1:b>
<n1:c name="attribute1" attribute2="attribute2">
THIS IS TAGGED TEXT
<span class="asd">THIS IS TAGGED TEXT
<span class="xyz">THIS IS TAGGED TEXT</span>
</span>
</n1:c>
THIS IS UNTAGGED TEXT
<n1:d name="attributeA" attribute2="attributeB">
THIS IS TAGGED TEXT
</n1:d>
</n1:b>
</n1:a>
</body>
</html>
这是所需的最终产品:
<html n1="namespace1" n2="namespace2">
<head>
<title>Document Title</title>
</head>
<body>
<untagged>THIS IS UNTAGGED TEXT</untagged>
<n1:a>
<n1:b>
<n1:c name="attribute1" attribute2="attribute2">
THIS IS TAGGED TEXT
<span class="asd">THIS IS TAGGED TEXT
<span class="xyz">THIS IS TAGGED TEXT</span>
</span>
</n1:c>
<untagged>THIS IS UNTAGGED TEXT</untagged>
<n1:d name="attributeA" attribute2="attributeB">
THIS IS TAGGED TEXT</n1:d>
</n1:b>
</n1:a>
</body>
</html>
我认为最好的方法是通过 IF 语句;我已经定义了 IF 语句的标准 - 即我能够从 XML 中 提取 未标记的文本并应用新元素 - 但是 不能附加 新元素为一个完整的输出。
这是我当前的不想要的输出:
<untagged>THIS IS UNTAGGED TEXT</untagged>
<untagged>THIS IS UNTAGGED TEXT</untagged>
这是我的 XQuery。
declare namespace n1="namespace1"
for $tag in /html/body//*/text()
return
if (
(
fn:namespace-uri($tag/parent::node()) = "namespace1"
and not(exists($tag/parent::node()/attribute::name))
or fn:namespace-uri($tag/parent::node()) != "namespace1"
)
and fn:normalize-space($tag) != ""
)
then <untagged>{$tag}</untagged>
else $tag
IF 语句是正确的,它返回任何文本: a) 属于命名空间但没有名称属性或 b) 不属于命名空间
我的问题是,如何在追加和打印新节点的同时仍保留原始 XML 结构并打印原始节点?
更新
在上面的 XML 中,我添加了几个 <span> 标记,这些标记应保留为标记文本,但是从下面的答案中使用的 XQuery 将其检测为未标记。
这是使用的新 XQuery:
declare function local:do(
$n as node()
) as node()*
{
typeswitch($n)
case element() return element { node-name($n) } {
for $child in $n/(@* | node())
return local:do($child)
}
case text() return
if ((fn:namespace-uri( $n/parent::node() ) != "namespace1"
(: *** recursive loop here? ***:)
and fn:normalize-space($n) != "")
or(fn:namespace-uri( $n/parent::node() ) = "namespace1"
and not( exists( $n/parent::node()/attribute::name) )
and fn:normalize-space($n) != "")
)
then element untagged { $n }
else $n
default return $n
};
local:do($xml)
这会将 <span> 文本放置在 <untagged> 元素内,而它应该保持包裹在 <span> 元素内。
我认为错误在于条件语句,如何改进?
【问题讨论】: