如何使用 xslt 将父节点命名空间复制到子元素?

Posted

技术标签:

【中文标题】如何使用 xslt 将父节点命名空间复制到子元素?【英文标题】:How to copy parent node namespace to child element using xslt? 【发布时间】:2020-01-24 09:05:30 【问题描述】:

我的 xml 看起来像我使用 Java JAXBContext 和 Marshaller 创建的。 我想格式化 xml 的某些部分,而不是整个 xml。

<?xml version="1.0" encoding="UTF-8"?>
<ns4:Requests xmlns:ns2="http://www.dummy.com/xsd/tublu/murmur_001" xmlns:ns3="http://www.dummy.com/xsd/CommonObjects_001" xmlns:ns4="http://www.dummy.com/xsd/naku_001">
   <ns4:RequestSetId>fhskgvseruigiu</ns4:RequestSetId>
   <ns4:RequestStream>CHAPP</ns4:RequestStream>
   <ns4:Request>
      <ns4:TrackAndTrace>
         <ns4:CPAId>003</ns4:CPAId>
         <ns4:CorrelationId>ytuty</ns4:CorrelationId>
      </ns4:TrackAndTrace>
   </ns4:Request>
   <ns4:Request>
      <ns4:TrackAndTrace>
         <ns4:CPAId>003</ns4:CPAId>
         <ns4:CorrelationId>cyuri7</ns4:CorrelationId>
      </ns4:TrackAndTrace>
   </ns4:Request>
</ns4:Requests>

我想格式化

<?xml version="1.0" encoding="UTF-8"?>
<ns4:Requests xmlns:ns2="http://www.dummy.com/xsd/tublu/murmur_001" xmlns:ns4="http://www.dummy.com/xsd/naku_001" xmlns:ns3="http://www.dummy.com/xsd/CommonObjects_001">
    <ns4:RequestSetId>fhskgvseruigiu</ns4:RequestSetId>
    <ns4:RequestStream>CHAPP</ns4:RequestStream>
    <ns4:Request xmlns:ns4="http://www.dummy.com/xsd/naku_001"><ns4:TrackAndTrace><ns4:CPAId>003</ns4:CPAId><ns4:CorrelationId>ytuty</ns4:CorrelationId></ns4:TrackAndTrace></ns4:Request>
    <ns4:Request xmlns:ns4="http://www.dummy.com/xsd/naku_001"><ns4:TrackAndTrace><ns4:CPAId>003</ns4:CPAId><ns4:CorrelationId>cyuri7</ns4:CorrelationId></ns4:TrackAndTrace></ns4:Request>
</ns4:Requests>

【问题讨论】:

“我想格式化 xml 的某些部分”是什么意思。我想,你想要每个节点树的单行格式。对吗? 是的,我想线性化一个完整的元素,在我的例子中是“请求”。 【参考方案1】:

这是解决方案(通过使用 Java 的 XSLT API 转换 XML 数据),

您可能也注意到了.. 单独的 JAXB 无法满足此要求,但在将对象编组为格式化的 XML 字符串(如您所示)之后,您可以使用合适的 XSLT 文件相应地对其进行后期处理/转换

所以要获得线性化的“请求”元素,只需使用如下所示的 xsl:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:strip-space elements="TrackAndTrace"/> 
    <xsl:strip-space elements="Request"/> 

    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

注意:还测试了上述方法/方法是否正常工作 - 使用了 Stylizer 示例代码(来自https://docs.oracle.com/javase/tutorial/jaxp/xslt/transformingXML.html)

干杯!

更新:如果您想要一个解决方案,同时保留问题中显示的原始命名空间前缀,请遵循此变体 添加 factory.setNamespaceAware(true);在样式器代码中 & 使用这个经过调整的 XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="w3.org/1999/XSL/Transform" xmlns:ns4="dummy.com/xsd/naku_001">
<xsl:strip-space elements="ns4:TrackAndTrace"/>
<xsl:strip-space elements="ns4:Request"/> 
   <xsl:template match="@*|node()">
       <xsl:copy>
           <xsl:apply-templates select="@*|node()"/>
       </xsl:copy>
   </xsl:template>
</xsl:stylesheet> 

【讨论】:

以上是关于如何使用 xslt 将父节点命名空间复制到子元素?的主要内容,如果未能解决你的问题,请参考以下文章

xslt copy-of到结果文档中的不同命名空间

使用命名空间时无法在 XSLT 中复制和修改属性

XSLT:复制 <mathml> 的所有子元素,不带 m: 命名空间,而无需为每个元素创建模板

如何使用 XSLT 替换命名空间中的元素?

除了使用扩展之外,如何在 XSLT 中处理自定义命名空间? [复制]

将父元素悬停到子标签元素后如何更改相同的css样式?