这是我想做的事情:
转换此XML:
<book author="Name" year="2000">Book title</book>
对于这个XML:
<book><author>Name</author><year>2000</year><value>Book title</value></book>
我想用xslt或者我可以从bash运行的东西...
感谢。
答案 0 :(得分:4)
此转化:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="@*">
<xsl:element name="{name()}">
<xsl:value-of select="."/>
</xsl:element>
</xsl:template>
<xsl:template match="text()">
<value>
<xsl:value-of select="."/>
</value>
</xsl:template>
</xsl:stylesheet>
应用于提供的XML文档:
<book author="Name" year="2000">Book title</book>
会产生想要的正确结果:
<book><author>Name</author><year>2000</year><value>Book title</value></book>
<强>解释强>:
identity rule/template “按原样”复制每个节点。
我们使用匹配任何属性的模板覆盖标识规则。它创建一个元素,其名称是匹配属性的名称,其唯一的text-node子元素是匹配属性的值。
最后,我们使用与任何文本节点匹配的模板覆盖标识规则。它只是输出包含在value
父元素中的节点。
请注意:使用和覆盖标识规则是最基本和最强大的XSLT设计模式。
我想用xslt或 我可以从bash运行的东西......
大多数XSLT处理器附带一个命令行实用程序,它从命令行调用XSLT转换。阅读您的XSLT处理器文档。
答案 1 :(得分:0)
这是使用xmlstarlet&amp; amp; Bash(它不保留标签顺序author-year-subvalue):
(
i=0
xmlstr='<book author="Name" year="2000">Book title</book>'
while IFS="" read -r -d $'\n' xpath; do
((i+=1))
name="$(printf '%s' "$xmlstr" | xmlstarlet sel -T -t -m "/${xpath}" -v "name(.)")"
value="$(printf '%s' "$xmlstr" | xmlstarlet sel -T -t -m "/${xpath}" -v '.')"
if [[ $i -eq 1 ]] || [[ "${xpath%/*}" != "${rootxpath}" ]]; then
rootxpath="${xpath%/*}"
subvalue="$(printf '%s' "$xmlstr" | xml sel -T -t -m "/${xpath}" -v '..')"
xmlstr="$(printf '%s' "$xmlstr" | xmlstarlet ed -u "/${xpath}/.." -v "" --subnode "." --type elem -n "$name" -v "$value" --subnode "." --type elem -n subvalue -v "$subvalue" )"
else
xmlstr="$(printf '%s' "$xmlstr" | xmlstarlet ed --subnode "/${xpath}/.." --type elem -n "$name" -v "$value")"
fi
printf '%s\n' "xpath: $xpath" "name: $name" "value: $value" "subvalue: $subvalue"; echo
done < <(echo "$xmlstr" | xmlstarlet el -a | LC_ALL=C sort -ru | grep -E '/@[^@]+$') # only get absolute paths that have attributes
# delete all attributes, move subvalues to the last position and format XML output
xmlstr="$(printf '%s\n' "$xmlstr" | xmlstarlet ed -d "//*/@*" -m "//subvalue" "." | tidy -q -xml | xmlstarlet fo -R -o -s 3 -)"
printf '%s\n\n' "$xmlstr"
printf '%s\n' "$xmlstr" | xmlstarlet sel -T -t -m "//book/*[1]" -v "name(.)" -o ': ' -v . -n
printf '%s\n' "$xmlstr" | xmlstarlet sel -T -t -m "//book/*[2]" -v "name(.)" -o ': ' -v . -n
printf '%s\n' "$xmlstr" | xmlstarlet sel -T -t -m "//book/*[3]" -v "name(.)" -o ': ' -v . -n
)
主要输出应为:
<book>
<year>2000</year>
<author>Name</author>
<subvalue>Book title</subvalue>
</book>