Другой вариант XSLT с xmlstarlet - использовать переменную, которая содержит обязательные элементы (со значениями по умолчанию или без них) и обрабатывать их как набор узлов (используя поддерживаемую функцию exsl:node-set()
).
You Затем можно выполнить итерацию по набору узлов, чтобы увидеть, существует ли элемент с таким именем. Если это так, используйте его. В противном случае используйте значение по умолчанию.
Пример ...
XML Вход (вход. xml)
<vendor>
<addresses>
<address primary="yes">
<line1>address 1 line1</line1>
<state>address 1 state1</state>
</address>
<address primary="no">
<line1>address 2 line1</line1>
<city>address 2 city</city>
<state>address 2 state</state>
</address>
</addresses>
</vendor>
XSLT 1.0 (so.xsl)
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exsl="http://exslt.org/common" exclude-result-prefixes="exsl">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:variable name="req_elems">
<req>
<line1/>
<city/>
<state/>
<country/>
</req>
</xsl:variable>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="address">
<xsl:variable name="ctx" select="."/>
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:for-each select="exsl:node-set($req_elems)/req/*">
<xsl:choose>
<xsl:when test="$ctx/*[local-name()=local-name(current())]">
<xsl:apply-templates select="$ctx/*[local-name()=local-name(current())]"/>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="."/>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
XML Выход
<vendor>
<addresses>
<address primary="yes">
<line1>address 1 line1</line1>
<city/>
<state>address 1 state1</state>
<country/>
</address>
<address primary="no">
<line1>address 2 line1</line1>
<city>address 2 city</city>
<state>address 2 state</state>
<country/>
</address>
</addresses>
</vendor>
Примечание. Это работает, только если в * разрешены только элементы 1023 * совпадают с $req_elements
. Например, если в адресе есть элемент с именем «foo», он будет удален из вывода.