使用 xmllint 解析 XML 并自定义输出

使用 xmllint 解析 XML 并自定义输出

我有以下架构的 xml 文件(例如 input.xml):

<?xml version="1.0"?>
  <TagA>
    <TagB>
      <File Folder="FOLDER1M\1" File="R1.txt" />
    </TagB>
    <TagB>
      <File Folder="FOLDER1M\2" File="R2.txt" />
    </TagB>
    <TagB>
      <File Folder="FOLDER2M\1" File="R3.txt" />
    </TagB>
  </TagA>

我需要解析这个文件并将输出写入另一个文件。所需的输出应采用以下形式:

www.xyz.com\FOLDER1M\1\R1.txt
www.xyz.com\FOLDER1M\2\R2.txt
www.xyz.com\FOLDER2M\1\R3.txt

到目前为止我得到的是:

echo 'cat /TagA/TagB/File/@*[name()="Folder" or name()="File"]' | xmllint --shell input.xml | grep '=' > xml_parsed

这给了我以下形式的o/p:

/ > cat /TagA/TagB/File/@*[name()="Folder" or name()="File"]
Folder="FOLDER1M\1"
File="R1.txt"
Folder="FOLDER1M\2"
File="R2.txt"
Folder="FOLDER2M\3"
File="R3.txt"

我应该如何获取所需的输出而不是当前的输出?

答案1

这是一种方法。我只是将您的输出放入名为 example.txt 的文件中,以使其更易于测试,您只需将我的命令附加到 echo 命令的末尾即可:

样本.txt

Folder="FOLDER1M\1"
File="R1.txt"
Folder="FOLDER1M\2"
File="R2.txt"
Folder="FOLDER2M\3"
File="R3.txt"

命令

% cat sample.txt | sed 'h;s/.*//;G;N;s/\n//g' | sed 's/Folder=\|"//g' | sed 's/File=/\\/' | sed 's/^/www.xyz.com\\/'

命令分解

将每 2 行连接在一起

# sed 'h;s/.*//;G;N;s/\n//g'
Folder="FOLDER1M\1"File="R1.txt"
Folder="FOLDER1M\2"File="R2.txt"
Folder="FOLDER2M\3"File="R3.txt"

删除文件夹= & "

# sed 's/Folder=\|"//g'
FOLDER1M\1File=R1.txt
FOLDER1M\2File=R2.txt
FOLDER2M\3File=R3.txt

将 File= 替换为 '\'

# sed 's/File=/\\/'
FOLDER1M\1\R1.txt
FOLDER1M\2\R2.txt
FOLDER2M\3\R3.txt

插入www.xyz.com

# sed 's/^/www.xyz.com\\/'
www.xyz.com\FOLDER1M\1\R1.txt
www.xyz.com\FOLDER1M\2\R2.txt
www.xyz.com\FOLDER2M\3\R3.txt

编辑#1

OP更新了他的问题,询问如何修改我的答案以删除第一行输出,例如:

/ > cat /TagA/TagB/File/@*[name()="Folder" or name()="File"]
...
...

我向他提到你可以用它grep -v ...来过滤掉不相关的行,如下所示:

% cat sample.txt | grep -v "/ >" | sed 'h;s/.*//;G;N;s/\n//g' | sed 's/Folder=\|"//g' | sed 's/File=/\\/' | sed 's/^/www.xyz.com\\/'

另外,要将整个位写入文件,可以像这样完成:

% cat sample.txt | grep -v "/ >" | sed 'h;s/.*//;G;N;s/\n//g' | sed 's/Folder=\|"//g' | sed 's/File=/\\/' | sed 's/^/www.xyz.com\\/' > /path/to/some/file.txt

答案2

xmllint使用它来执行此操作会很困难。

使用xmlstarlet

xmlstarlet sel -t \
    -m '//TagB/File' \
    -v 'concat("www.xyz.com", "\", @Folder, "\", @File)' \
    -nl file.xml

或者,要在命令行上安全地提供网站地址,

thesite=www.xyz.com
xmlstarlet sel -t --var site="'$thesite'" \
    -m '//TagB/File' \
    -v 'concat($site, "\", @Folder, "\", @File)' \
    -nl file.xml

TagB/File首先选择文档中所有节点的集合,然后,对于每个节点,将字符串www.xyz.com与属性值Folder和属性值File\在它们之间使用分隔符)连接起来。这-nl会导致在连接值之后发出换行符。

给出问题中的 XML 文档的输出:

www.xyz.com\FOLDER1M\1\R1.txt
www.xyz.com\FOLDER1M\2\R2.txt
www.xyz.com\FOLDER2M\1\R3.txt

相关内容