以下xmlstarlet命令:
./xmlstarlet-1.5.0/xml.exe fo --dropdtd $filename | ./xmlstarlet-1.5.0/xml.exe sel -t -m "//DOC//PTXT" -v "concat(./@ID,' ', .)"
返回多个结果,因为我的文件包含大量doc/ptxt
。我需要对每个输出做一些事情,更明确地我需要对每个ptxt值做一些事情。如何循环浏览XMLstarlet
的所有结果?
我的输出类似于:
my.id.one Text I need
my.id.two Text I also need
my.id.three Surprisingly I need this text too
我需要的是让每个id-text
对可能包含两个变量id
和text
,因为我有另一个包含id-value
对的文件,我需要匹配那些对。
更新1:
我需要做的具体例子:
我有档案X.xml
和档案Y.properties
文件X.xml
具有以下结构:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE DOC SYSTEM "ts.dtd">
<?xml-stylesheet type="text/css" href="ts.css"?>
<DOC LOCALE="en-US">
<PTXT ID="text.something">Open door</PTXT>
<PTXT ID="text.something.else">Open another door</PTXT>
<PTXT ID="text.whatever">Close all</PTXT>
</DOC>
文件Y.properties
具有以下结构:
text.something=Open window
text.something.else=Open another door
我期望的结果是Y.properties
这个内容:
text.something=Open door
text.something.else=Open another door
text.whatever=Close all
待办事项:
value
中id
的{{1}}与X.xml
中value
的{{1}}不同,key
来自Y.properties
value
中的{1}}应该更新。key
中Y.properties
的{{1}}与value
中id
的{{1}}相同,则无需执行任何操作X.xml
中value
的{{1}}在key
中不在Y.properties
,则应将id
从X.xml
添加到key
{1}} 我目前的shell代码是:
Y.properties
当前只从X.xml获取每个id /值并打印到std输出。
您可能怀疑value
就在那里,因为我有多个X.xml
和Y.properties
我必须执行此代码。
问题1: @janos我有以下问题,我真的不明白为什么。一切正常,但很少有人没有。例: X.xml:
for filename in C:/Temp/XLocation/*.xml; do
./xmlstarlet-1.5.0/xml.exe fo --dropdtd $filename | ./xmlstarlet-1.5.0/xml.exe sel -t -m "//DOC//PTXT" -v "concat(./@ID,' ', .)"
done
Y.properties:
for
我的输出是:
X.xml
请你帮助我,因为我真的不明白发生了什么。
问题2: 有以下输入: X.xml
Y.properties
和Y.properties
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE DOC SYSTEM "ts.dtd">
<?xml-stylesheet type="text/css" href="ts.css"?>
<DOC>
<PTXT ID="a.b.c.d" CONTEXT="label"><NTI>Text</NTI></PTXT>
</DOC>
导致: out.properties
a.b.c.d=Text
而不是
a.b.c.d=
Text=
=
答案 0 :(得分:1)
首先生成与Y.properties
中的格式匹配的数据:
xmlstarlet fo --dropdtd a.xml | \
xmlstarlet sel -t -m "//DOC//PTXT" -v $'concat(@ID, "=", ., "\n")'
对于你的例子,这会产生:
text.something=Open door
text.something.else=Open another door
text.whatever=Close all
然后您可以使用Awk执行以下逻辑:
-
Y.properties
作为第二个文件 =
作为分隔符,并使用简单的逻辑构建键值对的映射:如果键不在映射中,则添加键值对。
因为我们首先得到xmlstarlet
输出的行,
上面的逻辑会将所有这些值添加到映射中。
当我们处理第二个文件(Y.properties
)的行时,
其键已经在地图中的行将被忽略,
但是会添加新的键值对。像这样:
xmlstarlet fo --dropdtd a.xml | \
xmlstarlet sel -t -m "//DOC//PTXT" -v $'concat(@ID, "=", ., "\n")' | \
awk -F= '!($1 in m) { m[$1] = $2 }
END { for (key in m) { print key "=" m[key] } }' - Y.properties
您可以将输出重定向到所需的目标文件。
要对多个文件执行上述操作, 你可以将上面的代码包装在一个函数中, 有适当的参数。 例如:
mergeprops() {
local filename=$1
local propsfile=$2
local out=$3
xmlstarlet fo --dropdtd "$filename" | \
xmlstarlet sel -t -m "//DOC//PTXT" -v $'concat(@ID, "=", ., "\n")' | \
awk -F= '!($1 in m) { m[$1] = $2 }
END { for (key in m) { print key "=" m[key] } }' - "$propsfile" | sed 's/\s*=\s*/=/g' > "$out"
}
for filename in /c/Temp/XLocation/*.xml; do
mergeprops "$filename" Y.properties "$filename.out"
done
如果您需要更多帮助,请与我联系。