如果每个XML包含不同的URL,如何给出通用名称空间

时间:2017-11-02 18:52:05

标签: xml xslt xml-parsing xslt-1.0 xsl-fo

我有XML生成不同的命名空间,因此如何避免在xsl中使用名称空间并使用单个xsl获得低于结果的结果。或者我可以使用任何狂野的字符,如http://namesapce//example/*/format

输入1:

                <dynamic>
                    <rpc xmlns="http://namespace/example/123/format" >
                        <route>
                            <table>
                                <tablename>employee</tablename>
                                <count>20</count>
                            </table>
                            <table>
                                <tablename>employee</tablename>
                                <count> 21</count>
                                <rt> 1</rt>
                                <rt> 2</rt>
                                <rt> 3</rt>
                                <rt> 4</rt>
                            </table>
                            <table>
                                <tablename>dept</tablename>
                                <count>20</count>
                                <rt> a</rt>
                                <rt> b</rt>
                                <rt> c</rt>
                            </table>
                            <table>
                                <tablename>employee</tablename>
                                <count> 21</count>
                                <rt> 5</rt>
                                <rt> 6</rt>
                                <rt> 7</rt>
                                <rt> 8</rt>
                            </table>
                            <table>
                                <tablename>dept</tablename>
                                <count>44</count>
                                <rt> d</rt>
                                <rt> e</rt>
                                <rt> g</rt>
                            </table>
                        </route>
                    </rpc>
                </dynamic>

输入2:

<dynamic>
       <rpc xmlns="http://namespace/example/567/format" >
           <route>
            <table>

预期产出1:

<?xml version="1.0" encoding="UTF-8"?>
        <dynamic>
            <rpc xmlns="http://namespace/example">
                <route>
                    <table>
                        <tablename>employee</tablename>
                        <count>20</count>
                        <rt> 1</rt>
                        <rt> 2</rt>
                        <rt> 3</rt>
                        <rt> 4</rt>
                        <rt> 5</rt>
                        <rt> 6</rt>
                        <rt> 7</rt>
                        <rt> 8</rt>
                    </table>
                    <table>
                        <tablename>dept</tablename>
                        <count>20</count>
                        <rt> a</rt>
                        <rt> b</rt>
                        <rt> c</rt>
                        <rt> d</rt>
                        <rt> e</rt>
                        <rt> g</rt>
                    </table>
                </route>
            </rpc>
        </dynamic>

xml 2的输出2也包含名称空间,这个xsl应该能够处理任何类型的这种XML。

<?xml version="1.0" encoding="UTF-8"?><dynamic>
               <rpc xmlns="http://namespace/example/567/format">
                    <route>

2 个答案:

答案 0 :(得分:1)

进行两阶段转换。阶段1:标准化命名空间。阶段2:进行真正的转型工作。

这样可以最大限度地减少必须处理变体名称空间的代码量。

您可以使用

等代码规范化名称空间
<xsl:template match="old:*" xmlns:old="(old-namespace)" xmlns:new="(new namespace)">
   <xsl:element name="new:{local-name()">
     <xsl:apply-templates select="@*, node()"/>
   </xsl:element>
</xsl:template>

答案 1 :(得分:0)

您无法在命名空间URI中使用任何通配符,而使用XSLT 1.0,您无法使用*作为前缀。

也许starts-with()就足够了?

示例...

XML输入

<dynamic>
    <rpc xmlns="http://namespace/example/123/format" >
        <route>
            <table>
                <tablename>employee</tablename>
                <count>20</count>
            </table>
            <table>
                <tablename>employee</tablename>
                <count> 21</count>
                <rt> 1</rt>
                <rt> 2</rt>
                <rt> 3</rt>
                <rt> 4</rt>
            </table>
            <table>
                <tablename>dept</tablename>
                <count>20</count>
                <rt> a</rt>
                <rt> b</rt>
                <rt> c</rt>
            </table>
            <table>
                <tablename>employee</tablename>
                <count> 21</count>
                <rt> 5</rt>
                <rt> 6</rt>
                <rt> 7</rt>
                <rt> 8</rt>
            </table>
            <table>
                <tablename>dept</tablename>
                <count>44</count>
                <rt> d</rt>
                <rt> e</rt>
                <rt> g</rt>
            </table>
        </route>
    </rpc>
</dynamic>

XSLT 1.0

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <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="*[starts-with(namespace-uri(),'http://namespace/example')]">
    <xsl:element name="{local-name()}" namespace="http://namespace/example">
      <xsl:apply-templates select="@*|node()"/>
    </xsl:element>
  </xsl:template>

</xsl:stylesheet>

XML输出

<dynamic>
   <rpc xmlns="http://namespace/example">
      <route>
         <table>
            <tablename>employee</tablename>
            <count>20</count>
         </table>
         <table>
            <tablename>employee</tablename>
            <count> 21</count>
            <rt> 1</rt>
            <rt> 2</rt>
            <rt> 3</rt>
            <rt> 4</rt>
         </table>
         <table>
            <tablename>dept</tablename>
            <count>20</count>
            <rt> a</rt>
            <rt> b</rt>
            <rt> c</rt>
         </table>
         <table>
            <tablename>employee</tablename>
            <count> 21</count>
            <rt> 5</rt>
            <rt> 6</rt>
            <rt> 7</rt>
            <rt> 8</rt>
         </table>
         <table>
            <tablename>dept</tablename>
            <count>44</count>
            <rt> d</rt>
            <rt> e</rt>
            <rt> g</rt>
         </table>
      </route>
   </rpc>
</dynamic>
像迈克尔凯在他的回答中建议的那样,我分两个阶段做这个转变。第一阶段是这种转换以规范化命名空间。第二个转换将来自my other answer进行分组。

可能使用local-name()使我的原始变换更通用,但它很匆忙变得难看,我不推荐它。这是一个例子,你可以做出自己的决定。

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output indent="yes"/>
  <xsl:strip-space elements="*"/>

  <xsl:key name="table-by-name" match="*[local-name()='table']" use="*[local-name()='tablename']"/>

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

  <xsl:template match="*[starts-with(namespace-uri(),'http://namespace/example')]">
    <xsl:element name="{local-name()}" namespace="http://namespace/example">
      <xsl:apply-templates select="@*|node()"/>
    </xsl:element>
  </xsl:template>

  <xsl:template match="*[local-name()='route'][starts-with(namespace-uri(),'http://namespace/example')]"
    priority="1">
    <xsl:element name="{local-name()}" namespace="http://namespace/example">
      <xsl:for-each 
        select="*[local-name()='table'][count(.|key('table-by-name',*[local-name()='tablename'])[1])=1]">
        <xsl:element name="{local-name()}" namespace="http://namespace/example">
          <xsl:apply-templates 
            select="*[local-name()='tablename']|
            *[local-name()='count']|
            key('table-by-name',*[local-name()='tablename'])/*[local-name()='rt']"/>
        </xsl:element>
      </xsl:for-each>
    </xsl:element>
  </xsl:template>

</xsl:stylesheet>