在 WSO2 ESB 4.0.3 中删除带有空子元素的 XML 元素
Remove XML element with empty child in WSO2 ESB 4.0.3
我在 ESB 中设置了一个直通代理 Web 服务,它从 DSS 端点获取数据,类似于以下内容:
<Products xmlns="http://wso2.host.com/Products">
<Product>
<SKU>12345678</SKU>
<ItemName xmlns="null">T Shirt</ItemName>
<Restrictions>
<Restriction>
<Reason>Reason A</Reason>
<Code>12</Code>
</Restriction>
</Restrictions>
</Product>
</Products>
产品可能没有限制,并且会这样通过:
<Products xmlns="http://wso2.host.com/Products">
<Product>
<SKU>12345678</SKU>
<ItemName xmlns="null">T Shirt</ItemName>
<Restrictions>
<Restriction>
<Reason/>
<Code/>
</Restriction>
</Restrictions>
</Product>
</Products>
我想删除整个 <Restrictions>
元素,以便响应显示如下:
<Products xmlns="http://wso2.host.com/Products">
<Product>
<SKU>12345678</SKU>
<ItemName xmlns="null">T Shirt</ItemName>
</Product>
</Products>
我正在尝试在输出序列中使用 Enrich 调解器来替换它,但我不确定用什么来替换它,或者这是否真的是最好的方法。我的Xpath表达式如下:
/Products/Product/Restrictions[string-length(Restriction/Reason[text()])=0]
非常感谢任何帮助,我对 WSO2 不是很熟悉,可能完全没有找到正确的答案。提前致谢。
更新:我遵循了@Jorge Infante Osorio 的建议并添加了一个 XSLT 调解器,它引用了如下定义的本地条目:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" />
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Restrictions"/>
</xsl:stylesheet>
这仍然没有用。但是,我可以通过添加 3 个 XSLT 中介并将它们指向此本地条目来删除它们:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output omit-xml-declaration="yes" indent="yes" />
<xsl:strip-space elements="*" />
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*" />
</xsl:copy>
</xsl:template>
<xsl:template match="*[not(node())] | *[not(node()[2]) and node()/self::text() and not(normalize-space()) ] " />
</xsl:stylesheet>
我尝试修改它以匹配限制模板,就像@Jorge Infante Osorio 在他的示例中所使用的那样,但我似乎无法使其正确。
由于您的负载会根据输出不断变化,因此建议您使用 XSLT 中介,原因是您的序列会变小并且可读性会提高。
我的测试代理:
<?xml version="1.0" encoding="UTF-8"?>
<proxy xmlns="http://ws.apache.org/ns/synapse"
name="testReplacement"
transports="http https"
startOnLoad="true"
statistics="enable"
trace="enable">
<description/>
<target>
<inSequence>
<log level="custom">
<property name="ACCESO A: "
value="Accediendo replacement TEST"/>
</log>
<payloadFactory media-type="xml">
<format>
<Products xmlns="">
<Product>
<SKU>12345678</SKU>
<ItemName>T Shirt</ItemName>
<Restrictions>
<Restriction>
<Reason></Reason>
<Code></Code>
</Restriction>
</Restrictions>
</Product>
</Products>
</format>
<args>
</args>
</payloadFactory>
<property name="razon" expression="//Products/Product/Restrictions/Restriction/Reason/text()"/>
<property name="longitudValue" expression="fn:string-length(get-property('razon'))"/>
<log level="custom">
<property name="BODY = " expression="$ctx:body"/>
<property name="razon" expression="$ctx:razon"/>
<property name="longitudValue" expression="$ctx:longitudValue"/>
</log>
<filter source="$ctx:longitudValue" regex="0.0">
<then>
<log level="custom">
<property name="RESULTADO" value="Esta vacio"/>
</log>
<xslt key="transformacionDeleteEmpty"/>
<log level="custom">
<property name="BODY = " expression="$ctx:body"/>
</log>
</then>
<else>
<log level="custom">
<property name="RESULTADO" value="No esta vacio"/>
</log>
</else>
</filter>
<respond/>
</inSequence>
<outSequence>
<log level="full"/>
<drop/>
</outSequence>
<faultSequence/>
</target>
</proxy>
XSLT:
<?xml version="1.0" encoding="UTF-8"?>
<localEntry key="transformacionDeleteEmpty" xmlns="http://ws.apache.org/ns/synapse">
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" />
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Restrictions"/>
</xsl:stylesheet>
</localEntry>
控制台输出:
[2018-04-06 11:21:53,210] INFO - LogMediator ACCESO A: = Accediendo replacement TEST
[2018-04-06 11:21:53,214] INFO - LogMediator BODY = = <soapenv:Body xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope"><Products><Product><SKU>12345678</SKU><ItemName>T Shirt</I
temName><Restrictions><Restriction><Reason/><Code/></Restriction></Restrictions></Product></Products></soapenv:Body>, razon = , longitudValue = 0.0
[2018-04-06 11:21:53,215] INFO - LogMediator RESULTADO = Esta vacio
[2018-04-06 11:21:53,249] INFO - LogMediator BODY = = <soapenv:Body xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope"><Products>
<Product>
<SKU>12345678</SKU>
<ItemName>T Shirt</ItemName>
<Restrictions>
<Restriction>
<Reason/>
<Code/>
</Restriction>
</Restrictions>
</Product>
</Products></soapenv:Body>
[2018-04-06 11:21:53,307] INFO - LogMediator BODY = = <soapenv:Body xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope"><Products>
<Product>
<SKU>12345678</SKU>
<ItemName>T Shirt</ItemName>
</Product>
</Products></soapenv:Body>
尝试使用以下 XSLT...
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:p="http://wso2.host.com/Products">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="p:Restrictions[not(normalize-space())]"/>
</xsl:stylesheet>
请注意,我已经考虑了默认命名空间 http://wso2.host.com/Products
。
我在 ESB 中设置了一个直通代理 Web 服务,它从 DSS 端点获取数据,类似于以下内容:
<Products xmlns="http://wso2.host.com/Products">
<Product>
<SKU>12345678</SKU>
<ItemName xmlns="null">T Shirt</ItemName>
<Restrictions>
<Restriction>
<Reason>Reason A</Reason>
<Code>12</Code>
</Restriction>
</Restrictions>
</Product>
</Products>
产品可能没有限制,并且会这样通过:
<Products xmlns="http://wso2.host.com/Products">
<Product>
<SKU>12345678</SKU>
<ItemName xmlns="null">T Shirt</ItemName>
<Restrictions>
<Restriction>
<Reason/>
<Code/>
</Restriction>
</Restrictions>
</Product>
</Products>
我想删除整个 <Restrictions>
元素,以便响应显示如下:
<Products xmlns="http://wso2.host.com/Products">
<Product>
<SKU>12345678</SKU>
<ItemName xmlns="null">T Shirt</ItemName>
</Product>
</Products>
我正在尝试在输出序列中使用 Enrich 调解器来替换它,但我不确定用什么来替换它,或者这是否真的是最好的方法。我的Xpath表达式如下:
/Products/Product/Restrictions[string-length(Restriction/Reason[text()])=0]
非常感谢任何帮助,我对 WSO2 不是很熟悉,可能完全没有找到正确的答案。提前致谢。
更新:我遵循了@Jorge Infante Osorio 的建议并添加了一个 XSLT 调解器,它引用了如下定义的本地条目:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" />
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Restrictions"/>
</xsl:stylesheet>
这仍然没有用。但是,我可以通过添加 3 个 XSLT 中介并将它们指向此本地条目来删除它们:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output omit-xml-declaration="yes" indent="yes" />
<xsl:strip-space elements="*" />
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*" />
</xsl:copy>
</xsl:template>
<xsl:template match="*[not(node())] | *[not(node()[2]) and node()/self::text() and not(normalize-space()) ] " />
</xsl:stylesheet>
我尝试修改它以匹配限制模板,就像@Jorge Infante Osorio 在他的示例中所使用的那样,但我似乎无法使其正确。
由于您的负载会根据输出不断变化,因此建议您使用 XSLT 中介,原因是您的序列会变小并且可读性会提高。
我的测试代理:
<?xml version="1.0" encoding="UTF-8"?>
<proxy xmlns="http://ws.apache.org/ns/synapse"
name="testReplacement"
transports="http https"
startOnLoad="true"
statistics="enable"
trace="enable">
<description/>
<target>
<inSequence>
<log level="custom">
<property name="ACCESO A: "
value="Accediendo replacement TEST"/>
</log>
<payloadFactory media-type="xml">
<format>
<Products xmlns="">
<Product>
<SKU>12345678</SKU>
<ItemName>T Shirt</ItemName>
<Restrictions>
<Restriction>
<Reason></Reason>
<Code></Code>
</Restriction>
</Restrictions>
</Product>
</Products>
</format>
<args>
</args>
</payloadFactory>
<property name="razon" expression="//Products/Product/Restrictions/Restriction/Reason/text()"/>
<property name="longitudValue" expression="fn:string-length(get-property('razon'))"/>
<log level="custom">
<property name="BODY = " expression="$ctx:body"/>
<property name="razon" expression="$ctx:razon"/>
<property name="longitudValue" expression="$ctx:longitudValue"/>
</log>
<filter source="$ctx:longitudValue" regex="0.0">
<then>
<log level="custom">
<property name="RESULTADO" value="Esta vacio"/>
</log>
<xslt key="transformacionDeleteEmpty"/>
<log level="custom">
<property name="BODY = " expression="$ctx:body"/>
</log>
</then>
<else>
<log level="custom">
<property name="RESULTADO" value="No esta vacio"/>
</log>
</else>
</filter>
<respond/>
</inSequence>
<outSequence>
<log level="full"/>
<drop/>
</outSequence>
<faultSequence/>
</target>
</proxy>
XSLT:
<?xml version="1.0" encoding="UTF-8"?>
<localEntry key="transformacionDeleteEmpty" xmlns="http://ws.apache.org/ns/synapse">
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" />
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Restrictions"/>
</xsl:stylesheet>
</localEntry>
控制台输出:
[2018-04-06 11:21:53,210] INFO - LogMediator ACCESO A: = Accediendo replacement TEST
[2018-04-06 11:21:53,214] INFO - LogMediator BODY = = <soapenv:Body xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope"><Products><Product><SKU>12345678</SKU><ItemName>T Shirt</I
temName><Restrictions><Restriction><Reason/><Code/></Restriction></Restrictions></Product></Products></soapenv:Body>, razon = , longitudValue = 0.0
[2018-04-06 11:21:53,215] INFO - LogMediator RESULTADO = Esta vacio
[2018-04-06 11:21:53,249] INFO - LogMediator BODY = = <soapenv:Body xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope"><Products>
<Product>
<SKU>12345678</SKU>
<ItemName>T Shirt</ItemName>
<Restrictions>
<Restriction>
<Reason/>
<Code/>
</Restriction>
</Restrictions>
</Product>
</Products></soapenv:Body>
[2018-04-06 11:21:53,307] INFO - LogMediator BODY = = <soapenv:Body xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope"><Products>
<Product>
<SKU>12345678</SKU>
<ItemName>T Shirt</ItemName>
</Product>
</Products></soapenv:Body>
尝试使用以下 XSLT...
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:p="http://wso2.host.com/Products">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="p:Restrictions[not(normalize-space())]"/>
</xsl:stylesheet>
请注意,我已经考虑了默认命名空间 http://wso2.host.com/Products
。