使用 .xml 文件中的值更新 .properties 文件
Update .properties file with values from .xml file
以下 xmlstarlet 命令:
./xmlstarlet-1.5.0/xml.exe fo --dropdtd $filename | ./xmlstarlet-1.5.0/xml.exe sel -t -m "//DOC//PTXT" -v "concat(./@ID,' ', .)"
returns多个结果,因为我的文件包含很多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
in X.xml
不同于 value
来自 key
in Y.properties
,则 value
Y.properties
中的 key
应更新。
- 如果
X.xml
中的 id
中的 value
与 Y.properties
中的 key
中的 value
相同,则不应执行任何操作
- 如果
X.xml
中的 id
在 Y.properties
中不作为 key
出现,则应添加 X.xml
中的 value
至 Y.properties
我当前的shell代码是:
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
目前仅从 X.xml 获取每个 id/value 并打印到标准输出。
正如您可能怀疑的那样,for
在那里,因为我有多个 X.xml
和 Y.properties
,我必须在其上执行此代码。
问题一:
@janos 我有以下问题,我真的不明白为什么。一切正常,但很少有人不这样做。例子:
X.xml:
<?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>
Y.properties:
a.b.c.d=Text
我的输出是:
a.b.c.d=
Text=
=
你能帮帮我吗,我真的不明白发生了什么。
问题二:
具有以下输入:
X.xml
my.id = \u00D6ffnen Express WebTools
和Y.properties
<PTXT ID="my.id" CONTEXT="">Öffnen <NTI>Express WebTools</NTI></PTXT>
结果:
out.properties
my.id=Öffnen Express WebTools
my.id=\u00D6ffnen Express WebTools
而不是
my.id=Öffnen Express WebTools
首先生成数据以匹配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= '!( in m) { m[] = }
END { for (key in m) { print key "=" m[key] } }' - Y.properties
您可以将输出重定向到所需的目标文件。
要对多个文件执行上述操作,
您可以将上面的代码包装在一个函数中,
具有适当的参数。
例如:
mergeprops() {
local filename=
local propsfile=
local out=
xmlstarlet fo --dropdtd "$filename" | \
xmlstarlet sel -t -m "//DOC//PTXT" -v $'concat(@ID, "=", ., "\n")' | \
awk -F= '!( in m) { m[] = }
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
如果您需要更多帮助,请告诉我。
以下 xmlstarlet 命令:
./xmlstarlet-1.5.0/xml.exe fo --dropdtd $filename | ./xmlstarlet-1.5.0/xml.exe sel -t -m "//DOC//PTXT" -v "concat(./@ID,' ', .)"
returns多个结果,因为我的文件包含很多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
inX.xml
不同于value
来自key
inY.properties
,则value
Y.properties
中的key
应更新。 - 如果
X.xml
中的id
中的value
与Y.properties
中的key
中的value
相同,则不应执行任何操作 - 如果
X.xml
中的id
在Y.properties
中不作为key
出现,则应添加X.xml
中的value
至Y.properties
我当前的shell代码是:
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
目前仅从 X.xml 获取每个 id/value 并打印到标准输出。
正如您可能怀疑的那样,for
在那里,因为我有多个 X.xml
和 Y.properties
,我必须在其上执行此代码。
问题一: @janos 我有以下问题,我真的不明白为什么。一切正常,但很少有人不这样做。例子: X.xml:
<?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>
Y.properties:
a.b.c.d=Text
我的输出是:
a.b.c.d=
Text=
=
你能帮帮我吗,我真的不明白发生了什么。
问题二: 具有以下输入: X.xml
my.id = \u00D6ffnen Express WebTools
和Y.properties
<PTXT ID="my.id" CONTEXT="">Öffnen <NTI>Express WebTools</NTI></PTXT>
结果: out.properties
my.id=Öffnen Express WebTools
my.id=\u00D6ffnen Express WebTools
而不是
my.id=Öffnen Express WebTools
首先生成数据以匹配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= '!( in m) { m[] = }
END { for (key in m) { print key "=" m[key] } }' - Y.properties
您可以将输出重定向到所需的目标文件。
要对多个文件执行上述操作, 您可以将上面的代码包装在一个函数中, 具有适当的参数。 例如:
mergeprops() {
local filename=
local propsfile=
local out=
xmlstarlet fo --dropdtd "$filename" | \
xmlstarlet sel -t -m "//DOC//PTXT" -v $'concat(@ID, "=", ., "\n")' | \
awk -F= '!( in m) { m[] = }
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
如果您需要更多帮助,请告诉我。